* [PATCH v2 1/5] arm64: dts: hi3660: Add mailbox node
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526352795-6991-1-git-send-email-leo.yan@linaro.org>
From: Kaihua Zhong <zhongkaihua@huawei.com>
Add the mailbox controller node for hi3660 platform.
Signed-off-by: Kaihua Zhong <zhongkaihua@huawei.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index ec3eb8e..b9e7c91 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -274,6 +274,14 @@
#reset-cells = <2>;
};
+ mailbox: mailbox at e896b000 {
+ compatible = "hisilicon,hi3660-mbox";
+ reg = <0x0 0xe896b000 0x0 0x1000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <3>;
+ };
+
dual_timer0: timer at fff14000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x0 0xfff14000 0x0 0x1000>;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 0/5] Hi3660: enable power management features
From: Leo Yan @ 2018-05-15 2:53 UTC (permalink / raw)
To: linux-arm-kernel
Since hi3660 drivers have been merged into Linux kernel (mailbox driver is in
Linux-next branch and other drivers are existed in Linux mainline kernel), so
this patch series is to enable power management features on hi3660.
This patch series includes device tree binding for mailbox, stub clock and CPU
OPPs, and has one patch to consolidate the Kconfigs for driver modules.
This patch set have been tested on Hikey960 and also verified the patch 'hisi:
Consolidate the Kconfigs for the CLOCK_STUB and the MAILBOX' for Hikey620.
Changes from v1:
* Changed patch subject from "dts: arm64: hi3660" to "arm64: dts: hi3660".
Daniel Lezcano (1):
hisi: Consolidate the Kconfigs for the CLOCK_STUB and the MAILBOX
Kaihua Zhong (2):
arm64: dts: hi3660: Add mailbox node
arm64: dts: hi3660: Add stub clock node
Leo Yan (1):
arm64: dts: hi3660: Add CPU frequency scaling support
Tao Wang (1):
arm64: dts: hi3660: Add thermal cooling management
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 145 ++++++++++++++++++++++++++++++
arch/arm64/configs/defconfig | 1 -
drivers/clk/hisilicon/Kconfig | 13 +--
drivers/mailbox/Kconfig | 12 ++-
4 files changed, 161 insertions(+), 10 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 1/1] drm/mediatek: Add support for mediatek SOC MT2712
From: CK Hu @ 2018-05-15 2:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514095910.22618-2-stu.hsieh@mediatek.com>
Hi, Stu:
I've some inline comments.
On Mon, 2018-05-14 at 17:59 +0800, Stu Hsieh wrote:
> This patch add support for the Mediatek MT2712 DISP subsystem.
> There are two OVL engine and three disp output in MT2712.
>
> Signed-off-by: Stu Hsieh <stu.hsieh@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 77 ++++++++++++++++++++++++++---
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 ++
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 3 ++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 44 +++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 7 ++-
> 5 files changed, 127 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> index 8130f3dab661..641f4361b006 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> @@ -29,6 +29,8 @@
> #define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x084
> #define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN 0x088
> #define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac
> +#define DISP_REG_CONFIG_DISP_RDMA2_SOUT 0x0b8
> +#define DISP_REG_CONFIG_DISP_RDMA0_MOUT_EN 0x0c4
> #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8
> #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
>
> @@ -41,6 +43,7 @@
> #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
> #define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n))
> #define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
> +#define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
>
> #define INT_MUTEX BIT(1)
>
> @@ -60,6 +63,25 @@
> #define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24)
> #define MT8173_MUTEX_MOD_DISP_OD BIT(25)
>
> +#define MT2712_MUTEX_MOD_DISP_OVL0 BIT(11)
> +#define MT2712_MUTEX_MOD_DISP_OVL1 BIT(12)
> +#define MT2712_MUTEX_MOD_DISP_RDMA0 BIT(13)
> +#define MT2712_MUTEX_MOD_DISP_RDMA1 BIT(14)
> +#define MT2712_MUTEX_MOD_DISP_RDMA2 BIT(15)
> +#define MT2712_MUTEX_MOD_DISP_WDMA0 BIT(16)
> +#define MT2712_MUTEX_MOD_DISP_WDMA1 BIT(17)
> +#define MT2712_MUTEX_MOD_DISP_COLOR0 BIT(18)
> +#define MT2712_MUTEX_MOD_DISP_COLOR1 BIT(19)
> +#define MT2712_MUTEX_MOD_DISP_AAL BIT(20)
> +#define MT2712_MUTEX_MOD_DISP_UFOE BIT(22)
> +#define MT2712_MUTEX_MOD_DISP_PWM0 BIT(23)
> +#define MT2712_MUTEX_MOD_DISP_PWM1 BIT(24)
> +#define MT2712_MUTEX_MOD_DISP_PWM2 BIT(10)
> +#define MT2712_MUTEX_MOD_DISP_OD BIT(25)
> +/* modules more than 32, add BIT(31) when using DISP_REG_MUTEX_MOD2 bit */
> +#define MT2712_MUTEX_MOD2_DISP_AAL1 (BIT(1) | BIT(31))
> +#define MT2712_MUTEX_MOD2_DISP_OD1 (BIT(2) | BIT(31))
> +
It looks like that MUTEX_MOD definition varies for each SoC. I think
such definition should be passed from dts to prevent modify driver for
each SoC. For example, the clock definition varies for each SoC, and its
definition is placed in [1]. The dts [2] include the header file and
pass the clock definition to driver.
[1]
https://elixir.bootlin.com/linux/v4.17-rc5/source/include/dt-bindings/clock/mt2712-clk.h
[2]
https://elixir.bootlin.com/linux/v4.17-rc5/source/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
> #define MT2701_MUTEX_MOD_DISP_OVL BIT(3)
> #define MT2701_MUTEX_MOD_DISP_WDMA BIT(6)
> #define MT2701_MUTEX_MOD_DISP_COLOR BIT(7)
> @@ -74,6 +96,7 @@
>
> #define OVL0_MOUT_EN_COLOR0 0x1
> #define OD_MOUT_EN_RDMA0 0x1
> +#define OD1_MOUT_EN_RDMA1 BIT(16)
> #define UFOE_MOUT_EN_DSI0 0x1
> #define COLOR0_SEL_IN_OVL0 0x1
> #define OVL1_MOUT_EN_COLOR1 0x1
> @@ -108,6 +131,26 @@ static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
> [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
> };
>
> +static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
> + [DDP_COMPONENT_AAL] = MT2712_MUTEX_MOD_DISP_AAL,
> + [DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
> + [DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
> + [DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
> + [DDP_COMPONENT_OD] = MT2712_MUTEX_MOD_DISP_OD,
> + [DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
> + [DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
> + [DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
> + [DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
> + [DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
> + [DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
> + [DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
> + [DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
> + [DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
> + [DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
> + [DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
> + [DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
> +};
> +
> static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
> [DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
> [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
> @@ -150,6 +193,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
> } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
> *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
> value = GAMMA_MOUT_EN_RDMA1;
> + } else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) {
> + *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
> + value = OD1_MOUT_EN_RDMA1;
I think this should be moved to an independent patch and its title is
'add connection from OD1 to RDMA1'.
> } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
> *addr = DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN;
> value = RDMA1_MOUT_DPI0;
> @@ -278,6 +324,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
> struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
> mutex[mutex->id]);
> unsigned int reg;
> + unsigned int offset;
>
> WARN_ON(&ddp->mutex[mutex->id] != mutex);
>
> @@ -292,9 +339,17 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
> reg = MUTEX_SOF_DPI0;
> break;
> default:
> - reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
> - reg |= ddp->mutex_mod[id];
> - writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
> + if (ddp->mutex_mod[id] <= BIT(31)) {
You could reduce one byte if you write as
if (ddp->mutex_mod[id] < BIT(32))
> + offset = DISP_REG_MUTEX_MOD(mutex->id);
> + reg = readl_relaxed(ddp->regs + offset);
> + reg |= ddp->mutex_mod[id];
> + writel_relaxed(reg, ddp->regs + offset);
> + } else {
> + offset = DISP_REG_MUTEX_MOD2(mutex->id);
> + reg = readl_relaxed(ddp->regs + offset);
> + reg |= (ddp->mutex_mod[id] & ~BIT(31));
> + writel_relaxed(reg, ddp->regs + offset);
> + }
I think this should be moved to an independent patch and its title is
'support maximum 64 mutex mod'.
> return;
> }
>
> @@ -307,6 +362,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
> struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
> mutex[mutex->id]);
> unsigned int reg;
> + unsigned int offset;
>
> WARN_ON(&ddp->mutex[mutex->id] != mutex);
>
> @@ -318,9 +374,17 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
> ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
> break;
> default:
> - reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
> - reg &= ~(ddp->mutex_mod[id]);
> - writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
> + if (ddp->mutex_mod[id] <= BIT(31)) {
> + offset = DISP_REG_MUTEX_MOD(mutex->id);
> + reg = readl_relaxed(ddp->regs + offset);
> + reg &= ~(ddp->mutex_mod[id]);
> + writel_relaxed(reg, ddp->regs + offset);
> + } else {
> + offset = DISP_REG_MUTEX_MOD2(mutex->id);
> + reg = readl_relaxed(ddp->regs + offset);
> + reg &= ~(ddp->mutex_mod[id] & ~BIT(31));
> + writel_relaxed(reg, ddp->regs + offset);
> + }
> break;
> }
> }
> @@ -407,6 +471,7 @@ static int mtk_ddp_remove(struct platform_device *pdev)
>
> static const struct of_device_id ddp_driver_dt_match[] = {
> { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
> + { .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
> { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
> {},
> };
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> index 4672317e3ad1..ebe8f0018b31 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> @@ -219,6 +219,7 @@ struct mtk_ddp_comp_match {
>
> static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
> [DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, &ddp_aal },
> + [DDP_COMPONENT_AAL1] = { MTK_DISP_AAL, 1, &ddp_aal },
For the naming consistency, there are COLOR0 and COLOR1, so after you
add 'AAL1', you should change AAL to AAL0. And this modification should
be an independent patch.
> [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL },
> [DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, NULL },
> [DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, NULL },
> @@ -227,9 +228,12 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
> [DDP_COMPONENT_DSI1] = { MTK_DSI, 1, NULL },
> [DDP_COMPONENT_GAMMA] = { MTK_DISP_GAMMA, 0, &ddp_gamma },
> [DDP_COMPONENT_OD] = { MTK_DISP_OD, 0, &ddp_od },
> + [DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
Ditto.
> [DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, NULL },
> [DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, NULL },
> [DDP_COMPONENT_PWM0] = { MTK_DISP_PWM, 0, NULL },
> + [DDP_COMPONENT_PWM1] = { MTK_DISP_PWM, 1, NULL },
> + [DDP_COMPONENT_PWM2] = { MTK_DISP_PWM, 2, NULL },
> [DDP_COMPONENT_RDMA0] = { MTK_DISP_RDMA, 0, NULL },
> [DDP_COMPONENT_RDMA1] = { MTK_DISP_RDMA, 1, NULL },
> [DDP_COMPONENT_RDMA2] = { MTK_DISP_RDMA, 2, NULL },
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> index 0828cf8bf85c..43100f9215ae 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> @@ -42,6 +42,7 @@ enum mtk_ddp_comp_type {
>
> enum mtk_ddp_comp_id {
> DDP_COMPONENT_AAL,
> + DDP_COMPONENT_AAL1,
> DDP_COMPONENT_BLS,
> DDP_COMPONENT_COLOR0,
> DDP_COMPONENT_COLOR1,
> @@ -50,10 +51,12 @@ enum mtk_ddp_comp_id {
> DDP_COMPONENT_DSI1,
> DDP_COMPONENT_GAMMA,
> DDP_COMPONENT_OD,
> + DDP_COMPONENT_OD1,
> DDP_COMPONENT_OVL0,
> DDP_COMPONENT_OVL1,
> DDP_COMPONENT_PWM0,
> DDP_COMPONENT_PWM1,
> + DDP_COMPONENT_PWM2,
> DDP_COMPONENT_RDMA0,
> DDP_COMPONENT_RDMA1,
> DDP_COMPONENT_RDMA2,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index a2ca90fc403c..41baf6653bfc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -146,6 +146,32 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
> DDP_COMPONENT_DPI0,
> };
>
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = {
> + DDP_COMPONENT_OVL0,
> + DDP_COMPONENT_COLOR0,
> + DDP_COMPONENT_AAL,
> + DDP_COMPONENT_OD,
> + DDP_COMPONENT_RDMA0,
> + DDP_COMPONENT_DPI0,
> + DDP_COMPONENT_PWM0,
> +};
> +
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
> + DDP_COMPONENT_OVL1,
> + DDP_COMPONENT_COLOR1,
> + DDP_COMPONENT_AAL1,
> + DDP_COMPONENT_OD1,
> + DDP_COMPONENT_RDMA1,
> + DDP_COMPONENT_DPI1,
> + DDP_COMPONENT_PWM1,
> +};
> +
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
> + DDP_COMPONENT_RDMA2,
> + DDP_COMPONENT_DSI2,
> + DDP_COMPONENT_PWM2,
> +};
> +
It looks like that the path definition varies for each SoC. I think such
definition should be passed from dts to prevent modify driver for each
SoC. In [3], it define the partial connection in device tree, but I
would like this to be more general. My idea is:
1. Each component has one or two endpoint in device tree. The first and
the last has one, and the others has two.
2. Remove mtxxxx_mtk_ddp_main[] and mtxxxx_mtk_ddp_ext[], use multiple
link list (One display path has one link list, two display path has two
link list) to generate it by parsing device tree in mtk_drm_probe().
[3] https://patchwork.kernel.org/patch/10397337/
> static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
> DDP_COMPONENT_OVL0,
> DDP_COMPONENT_COLOR0,
> @@ -173,6 +199,15 @@ static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
> .shadow_register = true,
> };
>
> +static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
> + .main_path = mt2712_mtk_ddp_main,
> + .main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
> + .ext_path = mt2712_mtk_ddp_ext,
> + .ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
> + .third_path = mt2712_mtk_ddp_third,
> + .third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
> +};
> +
> static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
> .main_path = mt8173_mtk_ddp_main,
> .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
> @@ -232,6 +267,11 @@ static int mtk_drm_kms_init(struct drm_device *drm)
> if (ret < 0)
> goto err_component_unbind;
>
> + ret = mtk_drm_crtc_create(drm, private->data->third_path,
> + private->data->third_len);
> + if (ret < 0)
> + goto err_component_unbind;
> +
> /* Use OVL device for all DMA memory allocations */
> np = private->comp_node[private->data->main_path[0]] ?:
> private->comp_node[private->data->ext_path[0]];
> @@ -372,8 +412,10 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
> { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE },
> { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI },
> { .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI },
> + { .compatible = "mediatek,mt2712-dpi", .data = (void *)MTK_DPI },
Move this modification to the patch which modify the dpi driver for
mt2712.
> { .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI },
> { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
> + { .compatible = "mediatek,mt2712-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
> { .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
> { .compatible = "mediatek,mt2701-disp-pwm", .data = (void *)MTK_DISP_BLS },
> { .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM },
> @@ -552,6 +594,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
> static const struct of_device_id mtk_drm_of_ids[] = {
> { .compatible = "mediatek,mt2701-mmsys",
> .data = &mt2701_mmsys_driver_data},
> + { .compatible = "mediatek,mt2712-mmsys",
> + .data = &mt2712_mmsys_driver_data},
> { .compatible = "mediatek,mt8173-mmsys",
> .data = &mt8173_mmsys_driver_data},
> { }
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index c3378c452c0a..e821342bc2d3 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -17,8 +17,8 @@
> #include <linux/io.h>
> #include "mtk_drm_ddp_comp.h"
>
> -#define MAX_CRTC 2
> -#define MAX_CONNECTOR 2
> +#define MAX_CRTC 3
> +#define MAX_CONNECTOR 3
>
> struct device;
> struct device_node;
> @@ -33,6 +33,9 @@ struct mtk_mmsys_driver_data {
> unsigned int main_len;
> const enum mtk_ddp_comp_id *ext_path;
> unsigned int ext_len;
> + enum mtk_ddp_comp_id *third_path;
> + unsigned int third_len;
> +
> bool shadow_register;
> };
>
Regards,
CK
^ permalink raw reply
* [PATCH] ARM: dts: chromecast: override bad bootloader memory info
From: Jisheng Zhang @ 2018-05-15 2:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514215645.17592-2-tommyhebb@gmail.com>
Hi,
On Mon, 14 May 2018 17:56:45 -0400 Thomas Hebb wrote:
> On the Chromecast, the bootloader provides us with an ATAG_MEM of
> start=0x01000000 and size=0x3eff8000. This is clearly incorrect, as the
> range given encompasses nearly a GiB but the Chromecast only has 512MiB
> of RAM! Additionally, this causes the kernel to be decompressed at
> 0x00008000, below the claimed beginning of RAM, and so the boot fails.
>
> Since the existing ATAG parsing code runs before the kernel is even
> decompressed and irrevocably patches the device tree, don't even try
This means you enabled ARM_ATAG_DTB_COMPAT. could we disable it instead?
The ATAG is useless when we provide dtb. And IIRC, the ATAG is provided due
to legacy history code.
Thanks
> to bypass it. Instead, use the "linux,usable-memory" property instead
> of the "reg" property to define the real range. The ATAG code only
> overwrites reg, but linux,usable-memory is checked first in the OF
> driver, so the fact that reg gets changed makes no difference.
>
> Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
> ---
> arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
> index 20f31cdeaf38..54221f55bfa2 100644
> --- a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
> +++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
> @@ -52,7 +52,17 @@
>
> memory at 0 {
> device_type = "memory";
> - reg = <0x00000000 0x20000000>; /* 512 MB */
> +
> + /*
> + * We're using "linux,usable-memory" instead of "reg" here
> + * because the (signed and encrypted) bootloader that shipped
> + * with this device provides an incorrect memory range in
> + * ATAG_MEM. Linux helpfully overrides the "reg" property with
> + * data from the ATAG, so we can't specify the proper range
> + * normally. Fortunately, this alternate property is checked
> + * first by the OF driver, so we can (ab)use it instead.
> + */
> + linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
> };
>
> leds {
^ permalink raw reply
* [PATCH RESEND] clk: uniphier: add LD11/LD20 stream demux system clock
From: Katsuhiro Suzuki @ 2018-05-15 2:14 UTC (permalink / raw)
To: linux-arm-kernel
Add clock for MPEG2 transport stream I/O and demux system (HSC) on
UniPhier LD11/LD20 SoCs.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
drivers/clk/uniphier/clk-uniphier-sys.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c
index ebc78ab2df05..4f5ff9fa11fd 100644
--- a/drivers/clk/uniphier/clk-uniphier-sys.c
+++ b/drivers/clk/uniphier/clk-uniphier-sys.c
@@ -51,6 +51,9 @@
#define UNIPHIER_LD11_SYS_CLK_STDMAC(idx) \
UNIPHIER_CLK_GATE("stdmac", (idx), NULL, 0x210c, 8)
+#define UNIPHIER_LD11_SYS_CLK_HSC(idx) \
+ UNIPHIER_CLK_GATE("hsc", (idx), NULL, 0x210c, 9)
+
#define UNIPHIER_PRO4_SYS_CLK_GIO(idx) \
UNIPHIER_CLK_GATE("gio", (idx), NULL, 0x2104, 6)
@@ -182,6 +185,7 @@ const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = {
/* Index 5 reserved for eMMC PHY */
UNIPHIER_LD11_SYS_CLK_ETHER(6),
UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC, MIO */
+ UNIPHIER_LD11_SYS_CLK_HSC(9),
UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25),
UNIPHIER_LD11_SYS_CLK_AIO(40),
UNIPHIER_LD11_SYS_CLK_EVEA(41),
@@ -215,6 +219,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
UNIPHIER_LD20_SYS_CLK_SD,
UNIPHIER_LD11_SYS_CLK_ETHER(6),
UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC */
+ UNIPHIER_LD11_SYS_CLK_HSC(9),
/* GIO is always clock-enabled: no function for 0x210c bit5 */
/*
* clock for USB Link is enabled by the logic "OR" of bit 14 and bit 15.
--
2.17.0
^ permalink raw reply related
* [PATCH] media: helene: add I2C device probe function
From: Katsuhiro Suzuki @ 2018-05-15 2:05 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds I2C probe function to use dvb_module_probe()
with this driver.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
drivers/media/dvb-frontends/helene.c | 88 ++++++++++++++++++++++++++--
drivers/media/dvb-frontends/helene.h | 2 +
2 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index a0d0b53c91d7..04033f0c278b 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -666,7 +666,7 @@ static int helene_set_params_s(struct dvb_frontend *fe)
return 0;
}
-static int helene_set_params(struct dvb_frontend *fe)
+static int helene_set_params_t(struct dvb_frontend *fe)
{
u8 data[MAX_WRITE_REGSIZE];
u32 frequency;
@@ -835,6 +835,19 @@ static int helene_set_params(struct dvb_frontend *fe)
return 0;
}
+static int helene_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+ if (p->delivery_system == SYS_DVBT ||
+ p->delivery_system == SYS_DVBT2 ||
+ p->delivery_system == SYS_ISDBT ||
+ p->delivery_system == SYS_DVBC_ANNEX_A)
+ return helene_set_params_t(fe);
+
+ return helene_set_params_s(fe);
+}
+
static int helene_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct helene_priv *priv = fe->tuner_priv;
@@ -843,7 +856,7 @@ static int helene_get_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-static const struct dvb_tuner_ops helene_tuner_ops = {
+static const struct dvb_tuner_ops helene_tuner_ops_t = {
.info = {
.name = "Sony HELENE Ter tuner",
.frequency_min = 1000000,
@@ -853,7 +866,7 @@ static const struct dvb_tuner_ops helene_tuner_ops = {
.init = helene_init,
.release = helene_release,
.sleep = helene_sleep,
- .set_params = helene_set_params,
+ .set_params = helene_set_params_t,
.get_frequency = helene_get_frequency,
};
@@ -871,6 +884,20 @@ static const struct dvb_tuner_ops helene_tuner_ops_s = {
.get_frequency = helene_get_frequency,
};
+static const struct dvb_tuner_ops helene_tuner_ops = {
+ .info = {
+ .name = "Sony HELENE Sat/Ter tuner",
+ .frequency_min = 500000,
+ .frequency_max = 1200000000,
+ .frequency_step = 1000,
+ },
+ .init = helene_init,
+ .release = helene_release,
+ .sleep = helene_sleep,
+ .set_params = helene_set_params,
+ .get_frequency = helene_get_frequency,
+};
+
/* power-on tuner
* call once after reset
*/
@@ -1032,7 +1059,7 @@ struct dvb_frontend *helene_attach(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- memcpy(&fe->ops.tuner_ops, &helene_tuner_ops,
+ memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_t,
sizeof(struct dvb_tuner_ops));
fe->tuner_priv = priv;
dev_info(&priv->i2c->dev,
@@ -1042,6 +1069,59 @@ struct dvb_frontend *helene_attach(struct dvb_frontend *fe,
}
EXPORT_SYMBOL(helene_attach);
+static int helene_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct helene_config *config = client->dev.platform_data;
+ struct dvb_frontend *fe = config->fe;
+ struct device *dev = &client->dev;
+ struct helene_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->i2c_address = client->addr;
+ priv->i2c = client->adapter;
+ priv->set_tuner_data = config->set_tuner_priv;
+ priv->set_tuner = config->set_tuner_callback;
+ priv->xtal = config->xtal;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (helene_x_pon(priv) != 0)
+ return -EINVAL;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ memcpy(&fe->ops.tuner_ops, &helene_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+ fe->tuner_priv = priv;
+ i2c_set_clientdata(client, priv);
+
+ dev_info(dev, "Sony HELENE attached on addr=%x at I2C adapter %p\n",
+ priv->i2c_address, priv->i2c);
+
+ return 0;
+}
+
+static const struct i2c_device_id helene_id[] = {
+ { "helene", },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, helene_id);
+
+static struct i2c_driver helene_driver = {
+ .driver = {
+ .name = "helene",
+ },
+ .probe = helene_probe,
+ .id_table = helene_id,
+};
+module_i2c_driver(helene_driver);
+
MODULE_DESCRIPTION("Sony HELENE Sat/Ter tuner driver");
MODULE_AUTHOR("Abylay Ospan <aospan@netup.ru>");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/helene.h b/drivers/media/dvb-frontends/helene.h
index c9fc81c7e4e7..ceaa283708cb 100644
--- a/drivers/media/dvb-frontends/helene.h
+++ b/drivers/media/dvb-frontends/helene.h
@@ -46,6 +46,8 @@ struct helene_config {
void *set_tuner_priv;
int (*set_tuner_callback)(void *, int);
enum helene_xtal xtal;
+
+ struct dvb_frontend *fe;
};
#if IS_REACHABLE(CONFIG_DVB_HELENE)
--
2.17.0
^ permalink raw reply related
* [PATCH] KVM: arm/arm64: fix unaligned hva start and end in handle_hva_to_gpa
From: Jia He @ 2018-05-15 2:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <695beacb-ff51-bb2c-72ef-d268f7d4e59d@arm.com>
Hi Suzuki
I will merge the other thread into this, and add the necessary CC list
That WARN_ON call trace is very easy to reproduce in my armv8a server after I
start 20 guests
and run memhog in the host. Of course, ksm should be enabled
For you question about my inject fault debug patch:
diff --git a/mm/ksm.c b/mm/ksm.c
index e3cbf9a..876bec8 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -43,6 +43,8 @@
?#include <asm/tlbflush.h>
?#include "internal.h"
+int trigger_by_ksm = 0;
+
?#ifdef CONFIG_NUMA
?#define NUMA(x)??????????????? (x)
?#define DO_NUMA(x)???? do { (x); } while (0)
@@ -2587,11 +2589,14 @@ void rmap_walk_ksm(struct page *page, struct
rmap_walk_control *rwc)
??????????????????????? if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg))
??????????????????????????????? continue;
+trigger_by_ksm = 1;
??????????????????????? if (!rwc->rmap_one(page, vma,
??????????????????????????????????????? rmap_item->address, rwc->arg)) {
??????????????????????????????? anon_vma_unlock_read(anon_vma);
+trigger_by_ksm = 0;
??????????????????????????????? return;
??????????????????????? }
+trigger_by_ksm = 0;
??????????????????????? if (rwc->done && rwc->done(page)) {
??????????????????????????????? anon_vma_unlock_read(anon_vma);
??????????????????????????????? return;
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 7f6a944..ab8545e 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -290,12 +290,17 @@ static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd,
? * destroying the VM), otherwise another faulting VCPU may come in and mess
? * with things behind our backs.
? */
+extern int trigger_by_ksm;
?static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
?{
??????? pgd_t *pgd;
??????? phys_addr_t addr = start, end = start + size;
??????? phys_addr_t next;
+?????? if(trigger_by_ksm) {
+?????????????? end -= 0x200;
+?????? }
+
??????? assert_spin_locked(&kvm->mmu_lock);
??????? pgd = kvm->arch.pgd + stage2_pgd_index(addr);
??????? do {
I need to point out that I never reproduced it without this debugging patch.
Please also see my comments below
On 5/14/2018 6:06 PM, Suzuki K Poulose Wrote:
> On 14/05/18 03:30, Jia He wrote:
>>
>> On 5/11/2018 9:39 PM, Suzuki K Poulose Wrote:
>>> Marc
>>>
>>> Thanks for looping me in. Comments below.
>>>
>>>
>>> On 03/05/18 03:02, Jia He wrote:
>>>> Hi Marc
>>>>
>>>> Thanks for the review
>>>>
>>>>
>>>> On 5/2/2018 10:26 PM, Marc Zyngier Wrote:
>>>>> [+ Suzuki]
>>>>>
>>>>> On 02/05/18 08:08, Jia He wrote:
>>>>>> From: Jia He <jia.he@hxt-semitech.com>
>>>>>>
>>>>>> In our armv8a server (QDF2400), I noticed a WARN_ON as follows:
>>>>>>
>>>>>> [? 800.202850] WARNING: CPU: 33 PID: 255 at arch/arm64/kvm/../../../virt/kvm/arm/mmu.c:1670 kvm_age_hva_handler+0xcc/0xd4
>>>>> Which kernel version is that? I don't have a WARN_ON() at this line in
>>>>> 4.17. Do you have a reproducer?
>>>> My running kernel version is v4.14-15, but I can reproduced it in 4.17 (start 20 guests and run memhog in the host)
>>>> In 4.17, the warn_on is at
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/virt/kvm/arm/mmu.c#n1826
>>>>>> [? 800.213535] Modules linked in: vhost_net vhost tap xt_CHECKSUM ipt_MASQUERADE nf_nat_masquerade_ipv4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter rpcrdma ib_isert iscsi_target_mod ib_iser libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm vfat fat iw_cm mlx5_ib ib_core dm_mirror dm_region_hash dm_log dm_mod crc32_ce ipmi_ssif sg nfsd
>>>>>> [? 800.284115]? auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c mlx5_core ixgbe mlxfw devlink mdio ahci_platform libahci_platform qcom_emac libahci hdma hdma_mgmt i2c_qup
>>>>>> [? 800.300382] CPU: 33 PID: 255 Comm: khugepaged Tainted: G??????? W?????? 4.14.36+ #6
>>>>>> [? 800.308030] Hardware name: <snip for confidential issues>
>>>>> Well, that's QDF2400, right? ;-)
>>>> yes, exactly :)
>>>>>> [? 800.318717] task: ffff8017c949c000 task.stack: ffff8017c9498000
>>>>>> [? 800.324629] PC is at kvm_age_hva_handler+0xcc/0xd4
>>>>>> [? 800.329412] LR is at handle_hva_to_gpa+0xec/0x15c
>>>>>> [? 800.334109] pc : [<ffff0000080b4f2c>] lr : [<ffff0000080b4838>] pstate: 20400145
>>>>>> [? 800.341496] sp : ffff8017c949b260
>>>>>> [? 800.344804] x29: ffff8017c949b260 x28: ffff801663e25008
>>>>>> [? 800.350110] x27: 0000000000020000 x26: 00000001fb1a0000
>>>>>> [? 800.355416] x25: 0000ffff605b0200 x24: 0000ffff605a0200
>>>>>> [? 800.360722] x23: 0000000000000000 x22: 000000000000ffff
>>>>>> [? 800.366028] x21: 00000001fb1a0000 x20: ffff8017c085a000
>>>>>> [? 800.371334] x19: ffff801663e20008 x18: 0000000000000000
>>>>>> [? 800.376641] x17: 0000000000000000 x16: 0000000000000000
>>>>>> [? 800.381947] x15: 0000000000000000 x14: 3d646e655f617668
>>>>>> [? 800.387254] x13: 2c30303230623530 x12: 36666666663d646e
>>>>>> [? 800.392560] x11: 652c303032306135 x10: 3036666666663d74
>>>>>> [? 800.397867] x9 : 0000000000003796 x8 : 655f6e66672c3030
>>>>>> [? 800.403173] x7 : ffff00000859434c x6 : ffff8017f9c30cb8
>>>>>> [? 800.408479] x5 : ffff8017f9c30cb8 x4 : ffff0000080b4e60
>>>>>> [? 800.413786] x3 : 0000000000000000 x2 : 0000000000020000
>>>>>> [? 800.419092] x1 : 00000001fb1a0000 x0 : 0000000020000000
>>>>>> [? 800.424398] Call trace:
>>>>>> [? 800.426838] Exception stack(0xffff8017c949b120 to 0xffff8017c949b260)
>>>>>> [? 800.433272] b120: 0000000020000000 00000001fb1a0000 0000000000020000 0000000000000000
>>>>>> [? 800.441095] b140: ffff0000080b4e60 ffff8017f9c30cb8 ffff8017f9c30cb8 ffff00000859434c
>>>>>> [? 800.448918] b160: 655f6e66672c3030 0000000000003796 3036666666663d74 652c303032306135
>>>>>> [? 800.456740] b180: 36666666663d646e 2c30303230623530 3d646e655f617668 0000000000000000
>>>>>> [? 800.464563] b1a0: 0000000000000000 0000000000000000 0000000000000000 ffff801663e20008
>>>>>> [? 800.472385] b1c0: ffff8017c085a000 00000001fb1a0000 000000000000ffff 0000000000000000
>>>>>> [? 800.480208] b1e0: 0000ffff605a0200 0000ffff605b0200 00000001fb1a0000 0000000000020000
>>>>>> [? 800.488030] b200: ffff801663e25008 ffff8017c949b260 ffff0000080b4838 ffff8017c949b260
>>>>>> [? 800.495853] b220: ffff0000080b4f2c 0000000020400145 0000000000000001 ffff8017c949b2a0
>>>>>> [? 800.503676] b240: ffffffffffffffff ffff8017c949b260 ffff8017c949b260 ffff0000080b4f2c
>>>>>> [? 800.511498] [<ffff0000080b4f2c>] kvm_age_hva_handler+0xcc/0xd4
>>>>>> [? 800.517324] [<ffff0000080b4838>] handle_hva_to_gpa+0xec/0x15c
>>>>>> [? 800.523063] [<ffff0000080b6c5c>] kvm_age_hva+0x5c/0xcc
>>>>>> [? 800.528194] [<ffff0000080a7c3c>] kvm_mmu_notifier_clear_flush_young+0x54/0x90
>>>>>> [? 800.535324] [<ffff00000827a0e8>] __mmu_notifier_clear_flush_young+0x6c/0xa8
>>>>>> [? 800.542279] [<ffff00000825a644>] page_referenced_one+0x1e0/0x1fc
>>>>>> [? 800.548279] [<ffff00000827e8f8>] rmap_walk_ksm+0x124/0x1a0
>>>>>> [? 800.553759] [<ffff00000825c974>] rmap_walk+0x94/0x98
>>>>>> [? 800.558717] [<ffff00000825ca98>] page_referenced+0x120/0x180
>>>>>> [? 800.564369] [<ffff000008228c58>] shrink_active_list+0x218/0x4a4
>>>>>> [? 800.570281] [<ffff000008229470>] shrink_node_memcg+0x58c/0x6fc
>>>>>> [? 800.576107] [<ffff0000082296c4>] shrink_node+0xe4/0x328
>>>>>> [? 800.581325] [<ffff000008229c9c>] do_try_to_free_pages+0xe4/0x3b8
>>>>>> [? 800.587324] [<ffff00000822a094>] try_to_free_pages+0x124/0x234
>>>>>> [? 800.593150] [<ffff000008216aa0>] __alloc_pages_nodemask+0x564/0xf7c
>>>>>> [? 800.599412] [<ffff000008292814>] khugepaged_alloc_page+0x38/0xb8
>>>>>> [? 800.605411] [<ffff0000082933bc>] collapse_huge_page+0x74/0xd70
>>>>>> [? 800.611238] [<ffff00000829470c>] khugepaged_scan_mm_slot+0x654/0xa98
>>>>>> [? 800.617585] [<ffff000008294e0c>] khugepaged+0x2bc/0x49c
>>>>>> [? 800.622803] [<ffff0000080ffb70>] kthread+0x124/0x150
>>>>>> [? 800.627762] [<ffff0000080849f0>] ret_from_fork+0x10/0x1c
>>>>>> [? 800.633066] ---[ end trace 944c130b5252fb01 ]---
>>>>>> -------------------------------------------------------------------------
>>>>>>
>>>>>> The root cause might be: we can't guarantee that the parameter start and end
>>>>>> in handle_hva_to_gpa is PAGE_SIZE aligned, let alone hva_start and hva_end.
>>>>> So why not aligning them the first place?
>>>> at the first place of handle_hva_to_gpa()?
>>>> but boundary check is needed in each loop of kvm_for_each_memslot. Am I missing anything here?
>>>>>> This bug is introduced by commit 056aad67f836 ("kvm: arm/arm64: Rework gpa
>>>>>> callback handlers")
>>>>>>
>>>>>> It fixes the bug by use pfn size converted.
>>>>>>
>>>>>> Fixes: 056aad67f836 ("kvm: arm/arm64: Rework gpa callback handlers")
>>>>>>
>>>>>> Signed-off-by: jia.he at hxt-semitech.com
>>>>>> Signed-off-by: li.zhang at hxt-semitech.com
>>>>>> ---
>>>>>> ?? virt/kvm/arm/mmu.c | 10 ++++++----
>>>>>> ?? 1 file changed, 6 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
>>>>>> index 7f6a944..9dd7ae4 100644
>>>>>> --- a/virt/kvm/arm/mmu.c
>>>>>> +++ b/virt/kvm/arm/mmu.c
>>>>>> @@ -1744,7 +1744,7 @@ static int handle_hva_to_gpa(struct kvm *kvm,
>>>>>> ?????? /* we only care about the pages that the guest sees */
>>>>>> ?????? kvm_for_each_memslot(memslot, slots) {
>>>>>> ?????????? unsigned long hva_start, hva_end;
>>>>>> -??????? gfn_t gpa;
>>>>>> +??????? gpa_t gpa, gpa_end;
>>>>>> ?????????? hva_start = max(start, memslot->userspace_addr);
>>>>>> ?????????? hva_end = min(end, memslot->userspace_addr +
>>>>>> @@ -1753,7 +1753,9 @@ static int handle_hva_to_gpa(struct kvm *kvm,
>>>>>> ?????????????? continue;
>>>>>> ?????????? gpa = hva_to_gfn_memslot(hva_start, memslot) << PAGE_SHIFT;
>>>>>> -??????? ret |= handler(kvm, gpa, (u64)(hva_end - hva_start), data);
>>>>>> +??????? gpa_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot)
>>>>>> +???????????????????????????? << PAGE_SHIFT;
>>>>>> +??????? ret |= handler(kvm, gpa, (u64)(gpa_end - gpa), data);
>>>>> But we're looking for the mapping in the same memslot, so the distance
>>>>> between hva and hva_end is the same as the one between gpa and gpa_end
>>>>> if you didn't align it.
>>>> maybe not, sometimes hva_end-hva != gpa_end-gpa
>>>> start=fffdc37f0200,hva_start=fffdc37f0200,end=fffdc3800200,hva_end=fffdc3800000,gpa=3ff0000,gfn_end=4000000
>>>>
>>>> but sometimes it is:
>>>> start=ffff60590200,hva_start=ffff60590200,end=ffff605a0200,hva_end=ffff605a0200,gpa=1fb190000,gfn_end=1fb1b0000
>>>>
>>>> IMO, the unalignment is caused by the ksm stable page flag STABLE_FLAG. I will
>>>> propose another ksm patch to fix it?
>>>> But from handle_hva_to_gpa's point of view, arm kvm needs to void the followup
>>>> exception, just like what powerpc andx86 have done.
>>>
>>> As far as I can see this is triggered by someone (in this page_referenced_one via ksm?)
>>> triggering a clear_flush_young for a page, with a non-aligned page address.
>>>
>>> If you look at the code path, the __mmu_notifier_clear_flush_young is invoked
>>> via 2 code paths with the "given" address.
>>>
>>> ptep_clear_flush_young_notify(), in which case the end is set to + PAGE_SIZE
>>> pmdp_clear_flush_young_notify(), in which case the end is set to + PMD_SIZE
>>>
>>> We were supposed to only clear_flush_young for *the page* containing
>>> address (start), but we do a clear_flush_young for the next page
>>> as well, which (I think) is not something intended. So to me, it looks like, either
>>> page_referenced_one() or its caller must align the address to the PAGE_SIZE
>>> or PMD_SIZE depending on what it really wants to do, to avoid touching
>>> the adjacent entries (page or block pages).
>>>
>>> Suzuki
> Jia He,
>
>> Suzuki, thanks for the comments.
>>
>> I proposed another ksm patch https://lkml.org/lkml/2018/5/3/1042
>> The root cause is ksm will add some extra flags to indicate that the page
>> is in/not_in the stable tree. This makes address not be aligned with PAGE_SIZE.
> Thanks for the pointer. In the future, please Cc the people relevant to the
> discussion in the patches.
>
>> From arm kvm mmu point of view, do you think handle_hva_to_gpa still need to handle
>> the unalignment case?
> I don't think we should do that. Had we done this, we would never have caught this bug
> in KSM. Eventually if some other new implementation comes up with the a new notifier
> consumer which doesn't check alignment and doesn't WARN, it could simply do the wrong
> thing. So I believe what we have is a good measure to make sure that things are
> in the right order.
>
>> IMO, the PAGE_SIZE alignment is still needed because we should not let the bottom function
>> kvm_age_hva_handler to handle the exception. Please refer to the implementation in X86 and
>> powerpc kvm_handle_hva_range(). They both aligned the hva with hva_to_gfn_memslot.
>>
> From an API perspective, you are passed on a "start" and "end" address. So, you could potentially
> do the wrong thing if you align the "start" and "end". May be those handlers should also do the
> same thing as we do.
But handle_hva_to_gpa has partially adjusted the alignment possibly:
?? 1750???????? kvm_for_each_memslot(memslot, slots) {
?? 1751???????????????? unsigned long hva_start, hva_end;
?? 1752???????????????? gfn_t gpa;
?? 1753
?? 1754???????????????? hva_start = max(start, memslot->userspace_addr);
?? 1755???????????????? hva_end = min(end, memslot->userspace_addr +
?? 1756???????????????????????????? (memslot->npages << PAGE_SHIFT));
at line 1755, let us assume that end=0x12340200 and
memslot->userspace_addr + (memslot->npages << PAGE_SHIFT)=0x12340000
Then, hva_start is not page_size aligned and hva_end is aligned, and the size
will be PAGE_SIZE-0x200,
just as what I had done in the inject fault debugging patch.
--
Cheers,
Jia
^ permalink raw reply related
* [GIT PULL] arm64: dts: hisilicon dts updates for v4.18
From: Leo Yan @ 2018-05-15 1:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514200956.jzvglfib3kgjf6xs@localhost>
Hi Olof,
On Mon, May 14, 2018 at 01:09:56PM -0700, Olof Johansson wrote:
[...]
> > Leo Yan (1):
> > dts: arm64: hi3660: Add CPU frequency scaling support
> > Tao Wang (1):
> > dts: arm64: hi3660: Add thermal cooling management
> We try to use a very consistent patch prefix format on device tree changes to
> make it easier to get an overview, and you're unfortunately a bit inconsistent
> here.
>
> Would you mind respinning this with "arm64: dts: hi<...>:" as the consistent
> prefix please?
Sorry for this, I should take care for this ahead. Will respin the
patch series and send them out ASAP.
Thanks,
Leo Yan
^ permalink raw reply
* [PATCH 07/11] driver core: Respect all error codes from dev_pm_domain_attach()
From: Tony Lindgren @ 2018-05-15 0:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPDyKFqY5u3=db7-Xd9JXWo228PSNbH7-m-QNfSY9z8Z3p8t8A@mail.gmail.com>
* Ulf Hansson <ulf.hansson@linaro.org> [180514 18:59]:
> On 14 May 2018 at 17:19, Tony Lindgren <tony@atomide.com> wrote:
> > Reverting for 8c123c14bbba ("driver core: Respect all error codes from
> > dev_pm_domain_attach()") fixes the issue for me.
> >
> > Sounds like something is missing, any ideas?
>
> This should solve the problem:
>
> https://patchwork.kernel.org/patch/10398597/
Thanks yeah that fixes it for me too.
Regards,
Tony
^ permalink raw reply
* [PATCH] PM / Domains: Don't return -EEXIST at attach when PM domain exists
From: Tony Lindgren @ 2018-05-15 0:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526309557-7995-1-git-send-email-ulf.hansson@linaro.org>
* Ulf Hansson <ulf.hansson@linaro.org> [180514 14:55]:
> As dev_pm_domain_attach() isn't the only way to assign PM domain pointers
> to devices, clearly we must allow a device to have the pointer already
> being assigned. For this reason, return 0 instead of -EEXIST.
>
> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Reported-by: Krzysztof Kozlowski <krzk@kernel.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> Tested-by: Tested-by: Krzysztof Kozlowski <krzk@kernel.org>
Fixes the issue for me too:
Tested-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply
* [PATCH] media: dvb-frontends: add Socionext SC1501A ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-05-15 0:37 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds a frontend driver for the Socionext SC1501A series
and Socionext MN88443x ISDB-S/T demodulators.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
drivers/media/dvb-frontends/Kconfig | 10 +
drivers/media/dvb-frontends/Makefile | 1 +
drivers/media/dvb-frontends/sc1501a.c | 802 ++++++++++++++++++++++++++
drivers/media/dvb-frontends/sc1501a.h | 27 +
4 files changed, 840 insertions(+)
create mode 100644 drivers/media/dvb-frontends/sc1501a.c
create mode 100644 drivers/media/dvb-frontends/sc1501a.h
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 55e36a4f5215..e9d2c94b290e 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -739,6 +739,16 @@ config DVB_TC90522
Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
Say Y when you want to support this frontend.
+config DVB_SC1501A
+ tristate "Socionext SC1501A"
+ depends on DVB_CORE && I2C
+ select REGMAP_I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A driver for Socionext SC1501A, MN884433 and MN884434
+ ISDB-S + ISDB-T demodulator.
+ Say Y when you want to support this frontend.
+
comment "Digital terrestrial only tuners/PLL"
depends on DVB_CORE
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 67a783fd5ed0..e204502347ed 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_DVB_AF9033) += af9033.o
obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o
obj-$(CONFIG_DVB_TC90522) += tc90522.o
+obj-$(CONFIG_DVB_SC1501A) += sc1501a.o
obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
obj-$(CONFIG_DVB_HELENE) += helene.o
diff --git a/drivers/media/dvb-frontends/sc1501a.c b/drivers/media/dvb-frontends/sc1501a.c
new file mode 100644
index 000000000000..6460d7f95b35
--- /dev/null
+++ b/drivers/media/dvb-frontends/sc1501a.c
@@ -0,0 +1,802 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext SC1501A series demodulator driver for ISDB-S/ISDB-T.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <media/dvb_math.h>
+
+#include "sc1501a.h"
+
+/* ISDB-S registers */
+#define ATSIDU_S 0x2f
+#define ATSIDL_S 0x30
+#define TSSET_S 0x31
+#define AGCREAD_S 0x5a
+#define CPMON1_S 0x5e
+#define CPMON1_S_FSYNC BIT(5)
+#define CPMON1_S_ERRMON BIT(4)
+#define CPMON1_S_SIGOFF BIT(3)
+#define CPMON1_S_W2LOCK BIT(2)
+#define CPMON1_S_W1LOCK BIT(1)
+#define CPMON1_S_DW1LOCK BIT(0)
+#define TRMON_S 0x60
+#define BERCNFLG_S 0x68
+#define BERCNFLG_S_BERVRDY BIT(5)
+#define BERCNFLG_S_BERVCHK BIT(4)
+#define BERCNFLG_S_BERDRDY BIT(3)
+#define BERCNFLG_S_BERDCHK BIT(2)
+#define CNRDXU_S 0x69
+#define CNRDXL_S 0x6a
+#define CNRDYU_S 0x6b
+#define CNRDYL_S 0x6c
+#define BERVRDU_S 0x71
+#define BERVRDL_S 0x72
+#define DOSET1_S 0x73
+
+/* Primary ISDB-T */
+#define PLLASET1 0x00
+#define PLLASET2 0x01
+#define PLLBSET1 0x02
+#define PLLBSET2 0x03
+#define PLLSET 0x04
+#define OUTCSET 0x08
+#define OUTCSET_CHDRV_8MA 0xff
+#define OUTCSET_CHDRV_4MA 0x00
+#define PLDWSET 0x09
+#define PLDWSET_NORMAL 0x00
+#define PLDWSET_PULLDOWN 0xff
+#define HIZSET1 0x0a
+#define HIZSET2 0x0b
+
+/* Secondary ISDB-T (for MN884434 only) */
+#define RCVSET 0x00
+#define TSSET1_M 0x01
+#define TSSET2_M 0x02
+#define TSSET3_M 0x03
+#define INTACSET 0x08
+#define HIZSET3 0x0b
+
+/* ISDB-T registers */
+#define TSSET1 0x05
+#define TSSET1_TSASEL_MASK GENMASK(4, 3)
+#define TSSET1_TSASEL_ISDBT (0x0 << 3)
+#define TSSET1_TSASEL_ISDBS (0x1 << 3)
+#define TSSET1_TSASEL_NONE (0x2 << 3)
+#define TSSET1_TSBSEL_MASK GENMASK(2, 1)
+#define TSSET1_TSBSEL_ISDBS (0x0 << 1)
+#define TSSET1_TSBSEL_ISDBT (0x1 << 1)
+#define TSSET1_TSBSEL_NONE (0x2 << 1)
+#define TSSET2 0x06
+#define TSSET3 0x07
+#define TSSET3_INTASEL_MASK GENMASK(7, 6)
+#define TSSET3_INTASEL_T (0x0 << 6)
+#define TSSET3_INTASEL_S (0x1 << 6)
+#define TSSET3_INTASEL_NONE (0x2 << 6)
+#define TSSET3_INTBSEL_MASK GENMASK(5, 4)
+#define TSSET3_INTBSEL_S (0x0 << 4)
+#define TSSET3_INTBSEL_T (0x1 << 4)
+#define TSSET3_INTBSEL_NONE (0x2 << 4)
+#define OUTSET2 0x0d
+#define PWDSET 0x0f
+#define PWDSET_OFDMPD_MASK GENMASK(3, 2)
+#define PWDSET_OFDMPD_DOWN BIT(3)
+#define PWDSET_PSKPD_MASK GENMASK(1, 0)
+#define PWDSET_PSKPD_DOWN BIT(1)
+#define CLKSET1_T 0x11
+#define MDSET_T 0x13
+#define MDSET_T_MDAUTO_MASK GENMASK(7, 4)
+#define MDSET_T_MDAUTO_AUTO (0xf << 4)
+#define MDSET_T_MDAUTO_MANUAL (0x0 << 4)
+#define MDSET_T_FFTS_MASK GENMASK(3, 2)
+#define MDSET_T_FFTS_MODE1 (0x0 << 2)
+#define MDSET_T_FFTS_MODE2 (0x1 << 2)
+#define MDSET_T_FFTS_MODE3 (0x2 << 2)
+#define MDSET_T_GI_MASK GENMASK(1, 0)
+#define MDSET_T_GI_1_32 (0x0 << 0)
+#define MDSET_T_GI_1_16 (0x1 << 0)
+#define MDSET_T_GI_1_8 (0x2 << 0)
+#define MDSET_T_GI_1_4 (0x3 << 0)
+#define MDASET_T 0x14
+#define ADCSET1_T 0x20
+#define ADCSET1_T_REFSEL_MASK GENMASK(1, 0)
+#define ADCSET1_T_REFSEL_2V (0x3 << 0)
+#define ADCSET1_T_REFSEL_1_5V (0x2 << 0)
+#define ADCSET1_T_REFSEL_1V (0x1 << 0)
+#define NCOFREQU_T 0x24
+#define NCOFREQM_T 0x25
+#define NCOFREQL_T 0x26
+#define FADU_T 0x27
+#define FADM_T 0x28
+#define FADL_T 0x29
+#define AGCSET2_T 0x2c
+#define AGCSET2_T_IFPOLINV_INC BIT(0)
+#define AGCSET2_T_RFPOLINV_INC BIT(1)
+#define AGCV3_T 0x3e
+#define MDRD_T 0xa2
+#define MDRD_T_SEGID_MASK GENMASK(5, 4)
+#define MDRD_T_SEGID_13 (0x0 << 4)
+#define MDRD_T_SEGID_1 (0x1 << 4)
+#define MDRD_T_SEGID_3 (0x2 << 4)
+#define MDRD_T_FFTS_MASK GENMASK(3, 2)
+#define MDRD_T_FFTS_MODE1 (0x0 << 2)
+#define MDRD_T_FFTS_MODE2 (0x1 << 2)
+#define MDRD_T_FFTS_MODE3 (0x2 << 2)
+#define MDRD_T_GI_MASK GENMASK(1, 0)
+#define MDRD_T_GI_1_32 (0x0 << 0)
+#define MDRD_T_GI_1_16 (0x1 << 0)
+#define MDRD_T_GI_1_8 (0x2 << 0)
+#define MDRD_T_GI_1_4 (0x3 << 0)
+#define SSEQRD_T 0xa3
+#define SSEQRD_T_SSEQSTRD_MASK GENMASK(3, 0)
+#define SSEQRD_T_SSEQSTRD_RESET (0x0 << 0)
+#define SSEQRD_T_SSEQSTRD_TUNING (0x1 << 0)
+#define SSEQRD_T_SSEQSTRD_AGC (0x2 << 0)
+#define SSEQRD_T_SSEQSTRD_SEARCH (0x3 << 0)
+#define SSEQRD_T_SSEQSTRD_CLOCK_SYNC (0x4 << 0)
+#define SSEQRD_T_SSEQSTRD_FREQ_SYNC (0x8 << 0)
+#define SSEQRD_T_SSEQSTRD_FRAME_SYNC (0x9 << 0)
+#define SSEQRD_T_SSEQSTRD_SYNC (0xa << 0)
+#define SSEQRD_T_SSEQSTRD_LOCK (0xb << 0)
+#define AGCRDU_T 0xa8
+#define AGCRDL_T 0xa9
+#define CNRDU_T 0xbe
+#define CNRDL_T 0xbf
+#define BERFLG_T 0xc0
+#define BERFLG_T_BERDRDY BIT(7)
+#define BERFLG_T_BERDCHK BIT(6)
+#define BERFLG_T_BERVRDYA BIT(5)
+#define BERFLG_T_BERVCHKA BIT(4)
+#define BERFLG_T_BERVRDYB BIT(3)
+#define BERFLG_T_BERVCHKB BIT(2)
+#define BERFLG_T_BERVRDYC BIT(1)
+#define BERFLG_T_BERVCHKC BIT(0)
+#define BERRDU_T 0xc1
+#define BERRDM_T 0xc2
+#define BERRDL_T 0xc3
+#define BERLENRDU_T 0xc4
+#define BERLENRDL_T 0xc5
+#define ERRFLG_T 0xc6
+#define ERRFLG_T_BERDOVF BIT(7)
+#define ERRFLG_T_BERVOVFA BIT(6)
+#define ERRFLG_T_BERVOVFB BIT(5)
+#define ERRFLG_T_BERVOVFC BIT(4)
+#define ERRFLG_T_NERRFA BIT(3)
+#define ERRFLG_T_NERRFB BIT(2)
+#define ERRFLG_T_NERRFC BIT(1)
+#define ERRFLG_T_NERRF BIT(0)
+#define DOSET1_T 0xcf
+
+#define CLK_LOW 4000000
+#define CLK_DIRECT 20200000
+#define CLK_MAX 25410000
+
+#define S_T_FREQ 8126984 /* 512 / 63 MHz */
+
+struct sc1501a_spec {
+ bool primary;
+};
+
+struct sc1501a_priv {
+ const struct sc1501a_spec *spec;
+
+ struct dvb_frontend fe;
+ struct clk *mclk;
+ struct gpio_desc *reset_gpio;
+ u32 clk_freq;
+ u32 if_freq;
+
+ /* Common */
+ bool use_clkbuf;
+
+ /* ISDB-S */
+ struct i2c_client *client_s;
+ struct regmap *regmap_s;
+
+ /* ISDB-T */
+ struct i2c_client *client_t;
+ struct regmap *regmap_t;
+};
+
+static void sc1501a_cmn_power_on(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ clk_prepare_enable(chip->mclk);
+
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+ usleep_range(100, 1000);
+ gpiod_set_value_cansleep(chip->reset_gpio, 0);
+
+ if (chip->spec->primary) {
+ regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA);
+ regmap_write(r_t, PLDWSET, PLDWSET_NORMAL);
+ regmap_write(r_t, HIZSET1, 0x80);
+ regmap_write(r_t, HIZSET2, 0xe0);
+ } else {
+ regmap_write(r_t, HIZSET3, 0x8f);
+ }
+}
+
+static void sc1501a_cmn_power_off(struct sc1501a_priv *chip)
+{
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+
+ clk_disable_unprepare(chip->mclk);
+}
+
+static void sc1501a_s_sleep(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK,
+ PWDSET_PSKPD_DOWN);
+}
+
+static void sc1501a_s_wake(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0);
+}
+
+static void sc1501a_s_tune(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_s = chip->regmap_s;
+
+ regmap_write(r_s, ATSIDU_S, c->stream_id >> 8);
+ regmap_write(r_s, ATSIDL_S, c->stream_id);
+ regmap_write(r_s, TSSET_S, 0);
+}
+
+static int sc1501a_s_read_status(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_s = chip->regmap_s;
+ u32 cpmon, tmpu, tmpl, flg;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_s, CPMON1_S, &cpmon);
+
+ *status = 0;
+ if (cpmon & CPMON1_S_FSYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (cpmon & CPMON1_S_W2LOCK)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_s, AGCREAD_S, &tmpu);
+ agc = tmpu << 8;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr = 0, x, y, d;
+ u64 d_3 = 0;
+
+ regmap_read(r_s, CNRDXU_S, &tmpu);
+ regmap_read(r_s, CNRDXL_S, &tmpl);
+ x = (tmpu << 8) | tmpl;
+ regmap_read(r_s, CNRDYU_S, &tmpu);
+ regmap_read(r_s, CNRDYL_S, &tmpl);
+ y = (tmpu << 8) | tmpl;
+
+ /* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
+ /* D = x^2 / (2^15 * y - x^2) */
+ d = (y << 15) - x * x;
+ if (d > 0) {
+ /* (2^4 * D)^3 = 2^12 * D^3 */
+ /* 3.074 * 2^(12 + 24) = 211243671486 */
+ d_3 = div_u64(16 * x * x, d);
+ d_3 = d_3 * d_3 * d_3;
+ if (d_3)
+ d_3 = div_u64(211243671486, d_3);
+ }
+
+ if (d_3) {
+ /* 0.3 * 2^24 = 5033164 */
+ tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
+ - 5033164;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ }
+
+ if (cnr) {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_s, BERCNFLG_S, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_s, BERVRDU_S, &tmpu);
+ regmap_read(r_s, BERVRDL_S, &tmpl);
+ bit_err = (tmpu << 8) | tmpl;
+ bit_cnt = (1 << 13) * 204;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static void sc1501a_t_sleep(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK,
+ PWDSET_OFDMPD_DOWN);
+}
+
+static void sc1501a_t_wake(struct sc1501a_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0);
+}
+
+static bool sc1501a_t_is_valid_clk(u32 adckt, u32 if_freq)
+{
+ if (if_freq == DIRECT_IF_57MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= 21000000)
+ return true;
+ if (adckt >= 25300000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq == DIRECT_IF_44MHZ) {
+ if (adckt >= 25000000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= CLK_MAX)
+ return true;
+ }
+
+ return false;
+}
+
+static int sc1501a_t_set_freq(struct sc1501a_priv *chip)
+{
+ struct device *dev = &chip->client_s->dev;
+ struct regmap *r_t = chip->regmap_t;
+ s64 adckt, nco, ad_t;
+ u32 m, v;
+
+ /* Clock buffer (but not supported) or XTAL */
+ if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) {
+ chip->use_clkbuf = true;
+ regmap_write(r_t, CLKSET1_T, 0x07);
+
+ adckt = 0;
+ } else {
+ chip->use_clkbuf = false;
+ regmap_write(r_t, CLKSET1_T, 0x00);
+
+ adckt = chip->clk_freq;
+ }
+ if (!sc1501a_t_is_valid_clk(adckt, chip->if_freq)) {
+ dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n",
+ chip->clk_freq, adckt, chip->if_freq);
+ return -EINVAL;
+ }
+
+ /* Direct IF or Low IF */
+ if (chip->if_freq == DIRECT_IF_57MHZ ||
+ chip->if_freq == DIRECT_IF_44MHZ)
+ nco = adckt * 2 - chip->if_freq;
+ else
+ nco = -((s64)chip->if_freq);
+ nco = (nco << 24) / adckt;
+ ad_t = (adckt << 22) / S_T_FREQ;
+
+ regmap_write(r_t, NCOFREQU_T, nco >> 16);
+ regmap_write(r_t, NCOFREQM_T, nco >> 8);
+ regmap_write(r_t, NCOFREQL_T, nco);
+ regmap_write(r_t, FADU_T, ad_t >> 16);
+ regmap_write(r_t, FADM_T, ad_t >> 8);
+ regmap_write(r_t, FADL_T, ad_t);
+
+ /* Level of IF */
+ m = ADCSET1_T_REFSEL_MASK;
+ v = ADCSET1_T_REFSEL_1_5V;
+ regmap_update_bits(r_t, ADCSET1_T, m, v);
+
+ /* Polarity of AGC */
+ v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC;
+ regmap_update_bits(r_t, AGCSET2_T, v, v);
+
+ /* Lower output level of AGC */
+ regmap_write(r_t, AGCV3_T, 0x00);
+
+ regmap_write(r_t, MDSET_T, 0xfa);
+
+ return 0;
+}
+
+static void sc1501a_t_tune(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 m, v;
+
+ m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK;
+ v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8;
+ regmap_update_bits(r_t, MDSET_T, m, v);
+
+ regmap_write(r_t, MDASET_T, 0);
+}
+
+static int sc1501a_t_read_status(struct sc1501a_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 seqrd, st, flg, tmpu, tmpm, tmpl;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_t, SSEQRD_T, &seqrd);
+ st = seqrd & SSEQRD_T_SSEQSTRD_MASK;
+
+ *status = 0;
+ if (st >= SSEQRD_T_SSEQSTRD_SYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_t, AGCRDU_T, &tmpu);
+ regmap_read(r_t, AGCRDL_T, &tmpl);
+ agc = (tmpu << 8) | tmpl;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr;
+
+ regmap_read(r_t, CNRDU_T, &tmpu);
+ regmap_read(r_t, CNRDL_T, &tmpl);
+
+ if (tmpu || tmpl) {
+ /* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+ /* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */
+ tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl)
+ + 3355443;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ } else {
+ cnr = 0;
+ }
+
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_t, BERFLG_T, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_t, BERRDU_T, &tmpu);
+ regmap_read(r_t, BERRDM_T, &tmpm);
+ regmap_read(r_t, BERRDL_T, &tmpl);
+ bit_err = (tmpu << 16) | (tmpm << 8) | tmpl;
+
+ regmap_read(r_t, BERLENRDU_T, &tmpu);
+ regmap_read(r_t, BERLENRDL_T, &tmpl);
+ bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static int sc1501a_sleep(struct dvb_frontend *fe)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+
+ sc1501a_s_sleep(chip);
+ sc1501a_t_sleep(chip);
+
+ return 0;
+}
+
+static int sc1501a_set_frontend(struct dvb_frontend *fe)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct regmap *r_s = chip->regmap_s;
+ struct regmap *r_t = chip->regmap_t;
+ u8 tssel = 0, intsel = 0;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ sc1501a_s_wake(chip);
+ sc1501a_t_sleep(chip);
+
+ tssel = TSSET1_TSASEL_ISDBS;
+ intsel = TSSET3_INTASEL_S;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ sc1501a_s_sleep(chip);
+ sc1501a_t_wake(chip);
+
+ sc1501a_t_set_freq(chip);
+
+ tssel = TSSET1_TSASEL_ISDBT;
+ intsel = TSSET3_INTASEL_T;
+ }
+
+ regmap_update_bits(r_t, TSSET1,
+ TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK,
+ tssel | TSSET1_TSBSEL_NONE);
+ regmap_write(r_t, TSSET2, 0);
+ regmap_update_bits(r_t, TSSET3,
+ TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK,
+ intsel | TSSET3_INTBSEL_NONE);
+
+ regmap_write(r_t, DOSET1_T, 0x95);
+ regmap_write(r_s, DOSET1_S, 0x80);
+
+ if (c->delivery_system == SYS_ISDBS)
+ sc1501a_s_tune(chip, c);
+ else if (c->delivery_system == SYS_ISDBT)
+ sc1501a_t_tune(chip, c);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+static int sc1501a_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *s)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ s->min_delay_ms = 850;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ s->max_drift = 30000 * 2 + 1;
+ s->step_size = 30000;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ s->max_drift = 142857 * 2 + 1;
+ s->step_size = 142857 * 2;
+ }
+
+ return 0;
+}
+
+static int sc1501a_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct sc1501a_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->delivery_system == SYS_ISDBS)
+ return sc1501a_s_read_status(chip, c, status);
+
+ if (c->delivery_system == SYS_ISDBT)
+ return sc1501a_t_read_status(chip, c, status);
+
+ return -EINVAL;
+}
+
+static const struct dvb_frontend_ops sc1501a_ops = {
+ .delsys = { SYS_ISDBS, SYS_ISDBT },
+ .info = {
+ .name = "Socionext SC1501",
+ .frequency_min = 90000000,
+ .frequency_max = 2100000000,
+ .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .sleep = sc1501a_sleep,
+ .set_frontend = sc1501a_set_frontend,
+ .get_tune_settings = sc1501a_get_tune_settings,
+ .read_status = sc1501a_read_status,
+};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int sc1501a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct sc1501a_config *conf = client->dev.platform_data;
+ struct sc1501a_priv *chip;
+ struct device *dev = &client->dev;
+ int ret;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ if (dev->of_node)
+ chip->spec = of_device_get_match_data(dev);
+ else
+ chip->spec = (struct sc1501a_spec *)id->driver_data;
+ if (!chip->spec)
+ return -EINVAL;
+
+ chip->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(chip->mclk) && !conf) {
+ dev_err(dev, "Failed to request mclk: %ld\n",
+ PTR_ERR(chip->mclk));
+ return PTR_ERR(chip->mclk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "if-frequency",
+ &chip->if_freq);
+ if (ret && !conf) {
+ dev_err(dev, "Failed to load IF frequency: %d.\n", ret);
+ return ret;
+ }
+
+ chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(chip->reset_gpio)) {
+ dev_err(dev, "Failed to request reset_gpio: %ld\n",
+ PTR_ERR(chip->reset_gpio));
+ return PTR_ERR(chip->reset_gpio);
+ }
+
+ if (conf) {
+ chip->mclk = conf->mclk;
+ chip->if_freq = conf->if_freq;
+ chip->reset_gpio = conf->reset_gpio;
+
+ *conf->fe = &chip->fe;
+ }
+
+ chip->client_s = client;
+ chip->regmap_s = devm_regmap_init_i2c(chip->client_s, ®map_config);
+ if (IS_ERR(chip->regmap_s))
+ return PTR_ERR(chip->regmap_s);
+
+ /*
+ * Chip has two I2C addresses for each satellite/terrestrial system.
+ * ISDB-T uses address ISDB-S + 4, so we register a dummy client.
+ */
+ chip->client_t = i2c_new_dummy(client->adapter, client->addr + 4);
+ if (!chip->client_t)
+ return -ENODEV;
+
+ chip->regmap_t = devm_regmap_init_i2c(chip->client_t, ®map_config);
+ if (IS_ERR(chip->regmap_t)) {
+ ret = PTR_ERR(chip->regmap_t);
+ goto err_i2c_t;
+ }
+
+ chip->clk_freq = clk_get_rate(chip->mclk);
+
+ memcpy(&chip->fe.ops, &sc1501a_ops, sizeof(sc1501a_ops));
+ chip->fe.demodulator_priv = chip;
+ i2c_set_clientdata(client, chip);
+
+ sc1501a_cmn_power_on(chip);
+ sc1501a_s_sleep(chip);
+ sc1501a_t_sleep(chip);
+
+ return 0;
+
+err_i2c_t:
+ i2c_unregister_device(chip->client_t);
+
+ return ret;
+}
+
+static int sc1501a_remove(struct i2c_client *client)
+{
+ struct sc1501a_priv *chip = i2c_get_clientdata(client);
+
+ sc1501a_cmn_power_off(chip);
+
+ i2c_unregister_device(chip->client_t);
+
+ return 0;
+}
+
+static const struct sc1501a_spec sc1501a_spec_pri = {
+ .primary = true,
+};
+
+static const struct sc1501a_spec sc1501a_spec_sec = {
+ .primary = false,
+};
+
+static const struct of_device_id sc1501a_of_match[] = {
+ { .compatible = "socionext,mn884433", .data = &sc1501a_spec_pri, },
+ { .compatible = "socionext,mn884434-0", .data = &sc1501a_spec_pri, },
+ { .compatible = "socionext,mn884434-1", .data = &sc1501a_spec_sec, },
+ { .compatible = "socionext,sc1501a", .data = &sc1501a_spec_pri, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sc1501a_of_match);
+
+static const struct i2c_device_id sc1501a_i2c_id[] = {
+ { "mn884433", (kernel_ulong_t)&sc1501a_spec_pri },
+ { "mn884434-0", (kernel_ulong_t)&sc1501a_spec_pri },
+ { "mn884434-1", (kernel_ulong_t)&sc1501a_spec_sec },
+ { "sc1501a", (kernel_ulong_t)&sc1501a_spec_pri },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, sc1501a_i2c_id);
+
+static struct i2c_driver sc1501a_driver = {
+ .driver = {
+ .name = "sc1501a",
+ .of_match_table = of_match_ptr(sc1501a_of_match),
+ },
+ .probe = sc1501a_probe,
+ .remove = sc1501a_remove,
+ .id_table = sc1501a_i2c_id,
+};
+
+module_i2c_driver(sc1501a_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("Socionext SC1501A series demodulator driver.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/sc1501a.h b/drivers/media/dvb-frontends/sc1501a.h
new file mode 100644
index 000000000000..7e247d44e4ac
--- /dev/null
+++ b/drivers/media/dvb-frontends/sc1501a.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext SC1501A series demodulator driver for ISDB-S/ISDB-T.
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef SC1501A_H
+#define SC1501A_H
+
+#include <media/dvb_frontend.h>
+
+/* ISDB-T IF frequency */
+#define DIRECT_IF_57MHZ 57000000
+#define DIRECT_IF_44MHZ 44000000
+#define LOW_IF_4MHZ 4000000
+
+struct sc1501a_config {
+ struct clk *mclk;
+ u32 if_freq;
+ struct gpio_desc *reset_gpio;
+
+ /* Everything after that is returned by the driver. */
+ struct dvb_frontend **fe;
+};
+
+#endif /* SC1501A_H */
--
2.17.0
^ permalink raw reply related
* [Linux-c6x-dev] [PATCH 05/20] c6x: use generic dma_noncoherent_ops
From: Mark Salter @ 2018-05-15 0:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180511075945.16548-6-hch@lst.de>
On Fri, 2018-05-11 at 09:59 +0200, Christoph Hellwig wrote:
> Switch to the generic noncoherent direct mapping implementation.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> arch/c6x/Kconfig | 3 +
> arch/c6x/include/asm/Kbuild | 1 +
> arch/c6x/include/asm/dma-mapping.h | 28 ------
> arch/c6x/include/asm/setup.h | 2 +
> arch/c6x/kernel/Makefile | 2 +-
> arch/c6x/kernel/dma.c | 138 -----------------------------
> arch/c6x/mm/dma-coherent.c | 40 ++++++++-
> 7 files changed, 44 insertions(+), 170 deletions(-)
> delete mode 100644 arch/c6x/include/asm/dma-mapping.h
> delete mode 100644 arch/c6x/kernel/dma.c
>
> diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
> index 8c088b96e372..bf59855628ac 100644
> --- a/arch/c6x/Kconfig
> +++ b/arch/c6x/Kconfig
> @@ -6,7 +6,10 @@
>
> config C6X
> def_bool y
> + select ARCH_HAS_SYNC_DMA_FOR_CPU
> + select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> select CLKDEV_LOOKUP
> + select DMA_NONCOHERENT_OPS
> select GENERIC_ATOMIC64
> select GENERIC_IRQ_SHOW
> select HAVE_ARCH_TRACEHOOK
> diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
> index fd4c840de837..434600e47662 100644
> --- a/arch/c6x/include/asm/Kbuild
> +++ b/arch/c6x/include/asm/Kbuild
> @@ -5,6 +5,7 @@ generic-y += current.h
> generic-y += device.h
> generic-y += div64.h
> generic-y += dma.h
> +generic-y += dma-mapping.h
> generic-y += emergency-restart.h
> generic-y += exec.h
> generic-y += extable.h
> diff --git a/arch/c6x/include/asm/dma-mapping.h b/arch/c6x/include/asm/dma-mapping.h
> deleted file mode 100644
> index 05daf1038111..000000000000
> --- a/arch/c6x/include/asm/dma-mapping.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -/*
> - * Port on Texas Instruments TMS320C6x architecture
> - *
> - * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
> - * Author: Aurelien Jacquiot <aurelien.jacquiot@ti.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - */
> -#ifndef _ASM_C6X_DMA_MAPPING_H
> -#define _ASM_C6X_DMA_MAPPING_H
> -
> -extern const struct dma_map_ops c6x_dma_ops;
> -
> -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
> -{
> - return &c6x_dma_ops;
> -}
> -
> -extern void coherent_mem_init(u32 start, u32 size);
> -void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> - gfp_t gfp, unsigned long attrs);
> -void c6x_dma_free(struct device *dev, size_t size, void *vaddr,
> - dma_addr_t dma_handle, unsigned long attrs);
> -
> -#endif /* _ASM_C6X_DMA_MAPPING_H */
> diff --git a/arch/c6x/include/asm/setup.h b/arch/c6x/include/asm/setup.h
> index 852afb209afb..350f34debb19 100644
> --- a/arch/c6x/include/asm/setup.h
> +++ b/arch/c6x/include/asm/setup.h
> @@ -28,5 +28,7 @@ extern unsigned char c6x_fuse_mac[6];
> extern void machine_init(unsigned long dt_ptr);
> extern void time_init(void);
>
> +extern void coherent_mem_init(u32 start, u32 size);
> +
> #endif /* !__ASSEMBLY__ */
> #endif /* _ASM_C6X_SETUP_H */
> diff --git a/arch/c6x/kernel/Makefile b/arch/c6x/kernel/Makefile
> index 02f340d7b8fe..fbe74174de87 100644
> --- a/arch/c6x/kernel/Makefile
> +++ b/arch/c6x/kernel/Makefile
> @@ -8,6 +8,6 @@ extra-y := head.o vmlinux.lds
> obj-y := process.o traps.o irq.o signal.o ptrace.o
> obj-y += setup.o sys_c6x.o time.o devicetree.o
> obj-y += switch_to.o entry.o vectors.o c6x_ksyms.o
> -obj-y += soc.o dma.o
> +obj-y += soc.o
>
> obj-$(CONFIG_MODULES) += module.o
> diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c
> deleted file mode 100644
> index 31e1a9ec3a9c..000000000000
> --- a/arch/c6x/kernel/dma.c
> +++ /dev/null
> @@ -1,138 +0,0 @@
> -/*
> - * Copyright (C) 2011 Texas Instruments Incorporated
> - * Author: Mark Salter <msalter@redhat.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - */
> -#include <linux/module.h>
> -#include <linux/dma-mapping.h>
> -#include <linux/mm.h>
> -#include <linux/mm_types.h>
> -#include <linux/scatterlist.h>
> -
> -#include <asm/cacheflush.h>
> -
> -static void c6x_dma_sync(dma_addr_t handle, size_t size,
> - enum dma_data_direction dir)
> -{
> - unsigned long paddr = handle;
> -
> - BUG_ON(!valid_dma_direction(dir));
> -
> - switch (dir) {
> - case DMA_FROM_DEVICE:
> - L2_cache_block_invalidate(paddr, paddr + size);
> - break;
> - case DMA_TO_DEVICE:
> - L2_cache_block_writeback(paddr, paddr + size);
> - break;
> - case DMA_BIDIRECTIONAL:
> - L2_cache_block_writeback_invalidate(paddr, paddr + size);
> - break;
> - default:
> - break;
> - }
> -}
> -
> -static dma_addr_t c6x_dma_map_page(struct device *dev, struct page *page,
> - unsigned long offset, size_t size, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - dma_addr_t handle = virt_to_phys(page_address(page) + offset);
> -
> - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
> - c6x_dma_sync(handle, size, dir);
> -
> - return handle;
> -}
> -
> -static void c6x_dma_unmap_page(struct device *dev, dma_addr_t handle,
> - size_t size, enum dma_data_direction dir, unsigned long attrs)
> -{
> - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
> - c6x_dma_sync(handle, size, dir);
> -}
> -
> -static int c6x_dma_map_sg(struct device *dev, struct scatterlist *sglist,
> - int nents, enum dma_data_direction dir, unsigned long attrs)
> -{
> - struct scatterlist *sg;
> - int i;
> -
> - for_each_sg(sglist, sg, nents, i) {
> - sg->dma_address = sg_phys(sg);
> - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
> - c6x_dma_sync(sg->dma_address, sg->length, dir);
> - }
> -
> - return nents;
> -}
> -
> -static void c6x_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
> - int nents, enum dma_data_direction dir, unsigned long attrs)
> -{
> - struct scatterlist *sg;
> - int i;
> -
> - if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
> - return;
> -
> - for_each_sg(sglist, sg, nents, i)
> - c6x_dma_sync(sg_dma_address(sg), sg->length, dir);
> -}
> -
> -static void c6x_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
> - size_t size, enum dma_data_direction dir)
> -{
> - c6x_dma_sync(handle, size, dir);
> -
> -}
> -
> -static void c6x_dma_sync_single_for_device(struct device *dev,
> - dma_addr_t handle, size_t size, enum dma_data_direction dir)
> -{
> - c6x_dma_sync(handle, size, dir);
> -
> -}
> -
> -static void c6x_dma_sync_sg_for_cpu(struct device *dev,
> - struct scatterlist *sglist, int nents,
> - enum dma_data_direction dir)
> -{
> - struct scatterlist *sg;
> - int i;
> -
> - for_each_sg(sglist, sg, nents, i)
> - c6x_dma_sync_single_for_cpu(dev, sg_dma_address(sg),
> - sg->length, dir);
> -
> -}
> -
> -static void c6x_dma_sync_sg_for_device(struct device *dev,
> - struct scatterlist *sglist, int nents,
> - enum dma_data_direction dir)
> -{
> - struct scatterlist *sg;
> - int i;
> -
> - for_each_sg(sglist, sg, nents, i)
> - c6x_dma_sync_single_for_device(dev, sg_dma_address(sg),
> - sg->length, dir);
> -
> -}
> -
> -const struct dma_map_ops c6x_dma_ops = {
> - .alloc = c6x_dma_alloc,
> - .free = c6x_dma_free,
> - .map_page = c6x_dma_map_page,
> - .unmap_page = c6x_dma_unmap_page,
> - .map_sg = c6x_dma_map_sg,
> - .unmap_sg = c6x_dma_unmap_sg,
> - .sync_single_for_device = c6x_dma_sync_single_for_device,
> - .sync_single_for_cpu = c6x_dma_sync_single_for_cpu,
> - .sync_sg_for_device = c6x_dma_sync_sg_for_device,
> - .sync_sg_for_cpu = c6x_dma_sync_sg_for_cpu,
> -};
> -EXPORT_SYMBOL(c6x_dma_ops);
> diff --git a/arch/c6x/mm/dma-coherent.c b/arch/c6x/mm/dma-coherent.c
> index 95e38ad27c69..d0a8e0c4b27e 100644
> --- a/arch/c6x/mm/dma-coherent.c
> +++ b/arch/c6x/mm/dma-coherent.c
> @@ -19,10 +19,12 @@
> #include <linux/bitops.h>
> #include <linux/module.h>
> #include <linux/interrupt.h>
> -#include <linux/dma-mapping.h>
> +#include <linux/dma-noncoherent.h>
> #include <linux/memblock.h>
>
> +#include <asm/cacheflush.h>
> #include <asm/page.h>
> +#include <asm/setup.h>
>
> /*
> * DMA coherent memory management, can be redefined using the memdma=
> @@ -73,7 +75,7 @@ static void __free_dma_pages(u32 addr, int order)
> * Allocate DMA coherent memory space and return both the kernel
> * virtual and DMA address for that space.
> */
> -void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> gfp_t gfp, unsigned long attrs)
> {
> u32 paddr;
> @@ -98,7 +100,7 @@ void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> /*
> * Free DMA coherent memory as defined by the above mapping.
> */
> -void c6x_dma_free(struct device *dev, size_t size, void *vaddr,
> +void arch_dma_free(struct device *dev, size_t size, void *vaddr,
> dma_addr_t dma_handle, unsigned long attrs)
> {
> int order;
> @@ -139,3 +141,35 @@ void __init coherent_mem_init(phys_addr_t start, u32 size)
> dma_bitmap = phys_to_virt(bitmap_phys);
> memset(dma_bitmap, 0, dma_pages * PAGE_SIZE);
> }
> +
> +static void c6x_dma_sync(struct device *dev, phys_addr_t paddr, size_t size,
> + enum dma_data_direction dir)
> +{
> + BUG_ON(!valid_dma_direction(dir));
> +
> + switch (dir) {
> + case DMA_FROM_DEVICE:
> + L2_cache_block_invalidate(paddr, paddr + size);
> + break;
> + case DMA_TO_DEVICE:
> + L2_cache_block_writeback(paddr, paddr + size);
> + break;
> + case DMA_BIDIRECTIONAL:
> + L2_cache_block_writeback_invalidate(paddr, paddr + size);
> + break;
> + default:
> + break;
> + }
> +}
> +
> +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
> + size_t size, enum dma_data_direction dir)
> +{
> + return c6x_dma_sync(dev, paddr, size, dir);
> +}
> +
> +void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
> + size_t size, enum dma_data_direction dir)
> +{
> + return c6x_dma_sync(dev, paddr, size, dir);
> +}
Acked-by: Mark Salter <msalter@redhat.com>
^ permalink raw reply
* linux-next: manual merge of the samsung-krzk tree with the dma-mapping tree
From: Stephen Rothwell @ 2018-05-14 23:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180510091634.7fb3aaf2@canb.auug.org.au>
Hi all,
On Thu, 10 May 2018 09:16:34 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Today's linux-next merge of the samsung-krzk tree got a conflict in:
>
> arch/arm/mach-exynos/Kconfig
>
> between commit:
>
> 4965a68780c5 ("arch: define the ARCH_DMA_ADDR_T_64BIT config symbol in lib/Kconfig")
>
> from the dma-mapping tree and commit:
>
> c5deb598089c ("ARM: exynos: Remove support for Exynos5440")
>
> from the samsung-krzk tree.
>
> I fixed it up (the latter removed the whole section modified by
> the former, so I just removed the section) and can carry the fix as
> necessary. This is now fixed as far as linux-next is concerned, but any
> non trivial conflicts should be mentioned to your upstream maintainer
> when your tree is submitted for merging. You may also want to consider
> cooperating with the maintainer of the conflicting tree to minimise any
> particularly complex conflicts.
This is now a conflict between the arm-soc tree and the dma-mapping tree.
--
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180515/e2b00e44/attachment.sig>
^ permalink raw reply
* [PATCH 1/7] i2c: i2c-gpio: move header to platform_data
From: Greg Ungerer @ 2018-05-14 23:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514213719.o6ceftp2quem3s7f@ninjato>
Hi Wolfram,
On 15/05/18 07:37, Wolfram Sang wrote:
>> arch/arm/mach-ks8695/board-acs5k.c | 2 +-
>> arch/arm/mach-sa1100/simpad.c | 2 +-
>> arch/mips/alchemy/board-gpr.c | 2 +-
>
> Those still need acks...
>
>> diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
>> index 937eb1d47e7b..ef835d82cdb9 100644
>> --- a/arch/arm/mach-ks8695/board-acs5k.c
>> +++ b/arch/arm/mach-ks8695/board-acs5k.c
>> @@ -19,7 +19,7 @@
>> #include <linux/gpio/machine.h>
>> #include <linux/i2c.h>
>> #include <linux/i2c-algo-bit.h>
>> -#include <linux/i2c-gpio.h>
>> +#include <linux/platform_data/i2c-gpio.h>
>> #include <linux/platform_data/pca953x.h>
>>
>> #include <linux/mtd/mtd.h>
>
> ...
>
>> diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
>> index ace010479eb6..49a61e6f3c5f 100644
>> --- a/arch/arm/mach-sa1100/simpad.c
>> +++ b/arch/arm/mach-sa1100/simpad.c
>> @@ -37,7 +37,7 @@
>> #include <linux/input.h>
>> #include <linux/gpio_keys.h>
>> #include <linux/leds.h>
>> -#include <linux/i2c-gpio.h>
>> +#include <linux/platform_data/i2c-gpio.h>
>>
>> #include "generic.h"
>>
>> diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
>> index 4e79dbd54a33..fa75d75b5ba9 100644
>> --- a/arch/mips/alchemy/board-gpr.c
>> +++ b/arch/mips/alchemy/board-gpr.c
>> @@ -29,7 +29,7 @@
>> #include <linux/leds.h>
>> #include <linux/gpio.h>
>> #include <linux/i2c.h>
>> -#include <linux/i2c-gpio.h>
>> +#include <linux/platform_data/i2c-gpio.h>
>> #include <linux/gpio/machine.h>
>> #include <asm/bootinfo.h>
>> #include <asm/idle.h>
>
> ... and this was the shortened diff for those.
>
> Greg, Russell, Ralf, James? Is it okay if I take this via my tree?
Yes, I have no problem with that for the ks8695 part.
Acked-by: Greg Ungerer <gerg@uclinux.org>
Thanks
Greg
> Thanks,
>
> Wolfram
>
^ permalink raw reply
* [RFC PATCH 02/10] dt-bindings: devfreq: rk3399_dmc: Add rockchip,pmu phandle.
From: Chanwoo Choi @ 2018-05-14 22:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514211610.26618-3-enric.balletbo@collabora.com>
Hi,
On 2018? 05? 15? 06:16, Enric Balletbo i Serra wrote:
> The Rockchip DMC (Dynamic Memory Interface) needs to access to the PMU
> general register files to know the DRAM type, so add a phandle to the
> syscon that manages these registers.
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> ---
>
> Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
> index 0ec68141f85a..951789c0cdd6 100644
> --- a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
> +++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
> @@ -12,6 +12,8 @@ Required properties:
> for details.
> - center-supply: DMC supply node.
> - status: Marks the node enabled/disabled.
> +- rockchip,pmu: Phandle to the syscon managing the "PMU general register
> + files".
>
> Optional properties:
> - interrupts: The CPU interrupt number. The interrupt specifier
>
Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
^ permalink raw reply
* [RFC PATCH 03/10] devfreq: rk3399_dmc: Pass ODT and auto power down parameters to TF-A.
From: Chanwoo Choi @ 2018-05-14 22:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514211610.26618-4-enric.balletbo@collabora.com>
Hi,
On 2018? 05? 15? 06:16, Enric Balletbo i Serra wrote:
> Trusted Firmware-A (TF-A) for rk3399 implements a SiP call to get the
> on-die termination (ODT) and auto power down parameters from kernel,
> this patch adds the functionality to do this. Also, if DDR clock
> frequency is lower than the on-die termination (ODT) disable frequency
> this driver should disable the DDR ODT.
I have a question.
'disable frequency' is the same meaning of 'disable the DDR ODT'?
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> ---
>
> drivers/devfreq/rk3399_dmc.c | 50 ++++++++++++++++++++++++++++-
> include/soc/rockchip/rockchip_sip.h | 1 +
> 2 files changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
> index d5c03e5abe13..cc1bbca3fb15 100644
> --- a/drivers/devfreq/rk3399_dmc.c
> +++ b/drivers/devfreq/rk3399_dmc.c
> @@ -18,14 +18,17 @@
> #include <linux/devfreq.h>
> #include <linux/devfreq-event.h>
> #include <linux/interrupt.h>
> +#include <linux/mfd/syscon.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/platform_device.h>
> #include <linux/pm_opp.h>
> +#include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
> #include <linux/rwsem.h>
> #include <linux/suspend.h>
>
> +#include <soc/rockchip/rk3399_grf.h>
> #include <soc/rockchip/rockchip_sip.h>
>
> struct dram_timing {
> @@ -69,8 +72,11 @@ struct rk3399_dmcfreq {
> struct mutex lock;
> struct dram_timing timing;
> struct regulator *vdd_center;
> + struct regmap *regmap_pmu;
> unsigned long rate, target_rate;
> unsigned long volt, target_volt;
> + unsigned int odt_dis_freq;
> + int odt_pd_arg0, odt_pd_arg1;
> };
>
> static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
> @@ -80,6 +86,8 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
> struct dev_pm_opp *opp;
> unsigned long old_clk_rate = dmcfreq->rate;
> unsigned long target_volt, target_rate;
> + struct arm_smccc_res res;
> + int dram_flag;
> int err;
>
> opp = devfreq_recommended_opp(dev, freq, flags);
> @@ -95,6 +103,15 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
>
> mutex_lock(&dmcfreq->lock);
>
> + dram_flag = 0;
Also, if dram_flag is 0, it mean that disable ODT frequency?
If it's right, you better to define the precise variables as following
instead of just integer(0 or 1).
For example,
- ROCKCHIP_SIP_DRAM_FREQ_ENABLE
- ROCKCHIP_SIP_DRAM_FREQ_DISABLE
> + if (target_rate >= dmcfreq->odt_dis_freq)
> + dram_flag = 1;
> +
> + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0,
> + dmcfreq->odt_pd_arg1,
> + ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD,
> + dram_flag, 0, 0, 0, &res);
> +
This operation is special for only rk3399_dmc. It is difficult
to understand what to do. I recommend you better to add the detailed comment
with code.
> /*
> * If frequency scaling from low to high, adjust voltage first.
> * If frequency scaling from high to low, adjust frequency first.
> @@ -294,11 +311,13 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
> {
> struct arm_smccc_res res;
> struct device *dev = &pdev->dev;
> - struct device_node *np = pdev->dev.of_node;
> + struct device_node *np = pdev->dev.of_node, *node;
> struct rk3399_dmcfreq *data;
> int ret, index, size;
> uint32_t *timing;
> struct dev_pm_opp *opp;
> + u32 ddr_type;
> + u32 val;
>
> data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL);
> if (!data)
> @@ -334,6 +353,29 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
> return ret;
> }
>
> + /* Try to find the optional reference to the pmu syscon */
> + node = of_parse_phandle(np, "rockchip,pmu", 0);
> + if (node) {
> + data->regmap_pmu = syscon_node_to_regmap(node);
> + if (IS_ERR(data->regmap_pmu))
> + return PTR_ERR(data->regmap_pmu);
> + }
> +
> + /* Get DDR type */
> + regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
> + ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
> + RK3399_PMUGRF_DDRTYPE_MASK;
> +
> + /* Get the odt_dis_freq parameter in function of the DDR type */
> + if (ddr_type == RK3399_PMUGRF_DDRTYPE_DDR3)
> + data->odt_dis_freq = data->timing.ddr3_odt_dis_freq;
> + else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
> + data->odt_dis_freq = data->timing.lpddr3_odt_dis_freq;
> + else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
> + data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq;
> + else
> + return -EINVAL;
> +
how about using 'switch' statement?
> /*
> * Get dram timing and pass it to arm trust firmware,
> * the dram drvier in arm trust firmware will get these
> @@ -358,6 +400,12 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
> ROCKCHIP_SIP_CONFIG_DRAM_INIT,
> 0, 0, 0, 0, &res);
>
> + data->odt_pd_arg0 = (data->timing.sr_idle & 0xff) |
> + ((data->timing.sr_mc_gate_idle & 0xff) << 8) |
> + ((data->timing.standby_idle & 0xffff) << 16);
> + data->odt_pd_arg1 = (data->timing.pd_idle & 0xfff) |
> + ((data->timing.srpd_lite_idle & 0xfff) << 16);
> +
odt_pd_arg0 and odt_pd_arg1 might be used for disabling/enabling the ODT frequency.
As I commented, it depend on only rk3399_dmc. You better to add detailed comment.
And I prefer to define the XXX_SHIFT/XXX_MASK definition instead of
using 8/16/0xff/0xffff for the readability.
> /*
> * We add a devfreq driver to our parent since it has a device tree node
> * with operating points.
> diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h
> index 7e28092c4d3d..ad9482c56797 100644
> --- a/include/soc/rockchip/rockchip_sip.h
> +++ b/include/soc/rockchip/rockchip_sip.h
> @@ -23,5 +23,6 @@
> #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05
> #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06
> #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07
> +#define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08
>
> #endif
>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
^ permalink raw reply
* [PATCH v2] arm64: dts: qcom: Collapse usb support into one node
From: Stephen Boyd @ 2018-05-14 22:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1523973390-2387-1-git-send-email-yossim@codeaurora.org>
Quoting Yossi Mansharoff (2018-04-17 06:56:30)
> We currently have three device nodes for the same USB hardware
> block, as evident by the reuse of the same reg address multiple
> times. Now that the chipidea driver fully supports OTG with the
> MSM wrapper we can collapse all these nodes into one USB device
> node, reflecting the true nature of the hardware.
None of this makes sense. Commit text is totally bogus now.
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> index 9ff8487..1505921 100644
> --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
> @@ -371,18 +372,18 @@
> adp-disable;
> hnp-disable;
> srp-disable;
> - dr_mode = "host";
> - pinctrl-names = "default";
> - pinctrl-0 = <&usb_sw_sel_pm>;
> + mux-controls = <&usb_switch>;
> + mux-control-names = "usb_switch";
> +
> ulpi {
> phy {
> v1p8-supply = <&pm8916_l7>;
> v3p3-supply = <&pm8916_l13>;
> - extcon = <&usb_id>;
> };
> };
> };
>
> +
Why the newline?
> lpass at 7708000 {
> status = "okay";
> };
> @@ -512,11 +513,17 @@
>
> usb_id: usb-id {
> compatible = "linux,extcon-usb-gpio";
> - vbus-gpio = <&msmgpio 121 GPIO_ACTIVE_HIGH>;
> + id-gpio = <&msmgpio 121 GPIO_ACTIVE_HIGH>;
Hmm?
> pinctrl-names = "default";
> pinctrl-0 = <&usb_id_default>;
> };
>
> + usb_switch: usb-switch {
> + compatible = "gpio-mux";
Needs a better compatible string for the actual mux part. The gpio-mux
can come after that because it's generic, but it's good to record the
actual mux part too.
> + mux-gpios = <&pm8916_gpios 4 GPIO_ACTIVE_HIGH>;
> + #mux-control-cells = <0>;
> + };
^ permalink raw reply
* [PATCH 2/2] ARM: dts: chromecast: use PWM for LEDs
From: Thomas Hebb @ 2018-05-14 21:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <da60a97a0c6f754faa1f996334b3568ddb2f5ed0.1526334654.git.tommyhebb@gmail.com>
Control the Chromecast's two LEDs using PWM instead of GPIO pins. This
allows for variable brightness.
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---
.../boot/dts/berlin2cd-google-chromecast.dts | 20 ++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
index 54221f55bfa2..fb71e5436420 100644
--- a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
+++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
@@ -66,18 +66,21 @@
};
leds {
- compatible = "gpio-leds";
+ compatible = "pwm-leds";
+ pinctrl-0 = <&ledpwm_pmux>;
+ pinctrl-names = "default";
white {
label = "white";
- gpios = <&portc 1 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
+ pwms = <&pwm 0 600000 0>;
+ max-brightness = <255>;
+ linux,default-trigger = "default-on";
};
red {
label = "red";
- gpios = <&portc 2 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
+ pwms = <&pwm 1 600000 0>;
+ max-brightness = <255>;
};
};
};
@@ -96,3 +99,10 @@
&usb_phy1 { status = "okay"; };
&usb1 { status = "okay"; };
+
+&soc_pinctrl {
+ ledpwm_pmux: ledpwm-pmux {
+ groups = "G0";
+ function = "pwm";
+ };
+};
--
2.17.0
^ permalink raw reply related
* [PATCH] ARM: dts: chromecast: override bad bootloader memory info
From: Thomas Hebb @ 2018-05-14 21:56 UTC (permalink / raw)
To: linux-arm-kernel
On the Chromecast, the bootloader provides us with an ATAG_MEM of
start=0x01000000 and size=0x3eff8000. This is clearly incorrect, as the
range given encompasses nearly a GiB but the Chromecast only has 512MiB
of RAM! Additionally, this causes the kernel to be decompressed at
0x00008000, below the claimed beginning of RAM, and so the boot fails.
Since the existing ATAG parsing code runs before the kernel is even
decompressed and irrevocably patches the device tree, don't even try
to bypass it. Instead, use the "linux,usable-memory" property instead
of the "reg" property to define the real range. The ATAG code only
overwrites reg, but linux,usable-memory is checked first in the OF
driver, so the fact that reg gets changed makes no difference.
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---
arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
index 20f31cdeaf38..54221f55bfa2 100644
--- a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
+++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
@@ -52,7 +52,17 @@
memory at 0 {
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512 MB */
+
+ /*
+ * We're using "linux,usable-memory" instead of "reg" here
+ * because the (signed and encrypted) bootloader that shipped
+ * with this device provides an incorrect memory range in
+ * ATAG_MEM. Linux helpfully overrides the "reg" property with
+ * data from the ATAG, so we can't specify the proper range
+ * normally. Fortunately, this alternate property is checked
+ * first by the OF driver, so we can (ab)use it instead.
+ */
+ linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
};
leds {
--
2.17.0
^ permalink raw reply related
* [PATCH 1/4] amba: Export amba_bustype
From: Kim Phillips @ 2018-05-14 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <19c4b830-9f50-d5ea-3e31-587477210ee1@arm.com>
On Wed, 9 May 2018 17:02:34 +0100
Robin Murphy <robin.murphy@arm.com> wrote:
> probe (and thus call coresight_register()) first. Oh well, I guess
> poking amba_bustype really does remain the only reasonable answer.
Thanks all, I've added Robin's Reviewed-by, and submitted this patch to
RMK's patch tracking system, here:
http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8773/1
Cheers,
Kim
^ permalink raw reply
* [RFC PATCH 01/10] devfreq: rockchip-dfi: Move GRF definitions to a common place.
From: Chanwoo Choi @ 2018-05-14 21:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514211610.26618-2-enric.balletbo@collabora.com>
Hi Enric,
On 2018? 05? 15? 06:16, Enric Balletbo i Serra wrote:
> Some rk3399 GRF (Generic Register Files) definitions can be used for
> different drivers. Move these definitions to a common include so we
> don't need to duplicate these definitions.
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> ---
>
> drivers/devfreq/event/rockchip-dfi.c | 23 +++++++----------------
> include/soc/rockchip/rk3399_grf.h | 21 +++++++++++++++++++++
> 2 files changed, 28 insertions(+), 16 deletions(-)
> create mode 100644 include/soc/rockchip/rk3399_grf.h
>
> diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
> index 22b113363ffc..2fbbcbeb644f 100644
> --- a/drivers/devfreq/event/rockchip-dfi.c
> +++ b/drivers/devfreq/event/rockchip-dfi.c
> @@ -26,6 +26,8 @@
> #include <linux/list.h>
> #include <linux/of.h>
>
> +#include <soc/rockchip/rk3399_grf.h>
> +
> #define RK3399_DMC_NUM_CH 2
>
> /* DDRMON_CTRL */
> @@ -43,18 +45,6 @@
> #define DDRMON_CH1_COUNT_NUM 0x3c
> #define DDRMON_CH1_DFI_ACCESS_NUM 0x40
>
> -/* pmu grf */
> -#define PMUGRF_OS_REG2 0x308
> -#define DDRTYPE_SHIFT 13
> -#define DDRTYPE_MASK 7
> -
> -enum {
> - DDR3 = 3,
> - LPDDR3 = 6,
> - LPDDR4 = 7,
> - UNUSED = 0xFF
> -};
> -
> struct dmc_usage {
> u32 access;
> u32 total;
> @@ -83,16 +73,17 @@ static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
> u32 ddr_type;
>
> /* get ddr type */
> - regmap_read(info->regmap_pmu, PMUGRF_OS_REG2, &val);
> - ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
> + regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
> + ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
> + RK3399_PMUGRF_DDRTYPE_MASK;
>
> /* clear DDRMON_CTRL setting */
> writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
>
> /* set ddr type to dfi */
> - if (ddr_type == LPDDR3)
> + if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
> writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
> - else if (ddr_type == LPDDR4)
> + else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
> writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
>
> /* enable count, use software mode */
> diff --git a/include/soc/rockchip/rk3399_grf.h b/include/soc/rockchip/rk3399_grf.h
> new file mode 100644
> index 000000000000..0f94034e2e9a
> --- /dev/null
> +++ b/include/soc/rockchip/rk3399_grf.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Rockchip Generic Register Files definitions
> + *
> + * Copyright (c) 2018, Collabora Ltd.
> + * Author: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> + */
> +
> +#ifndef __SOC_RK3399_GRF_H
> +#define __SOC_RK3399_GRF_H
> +
> +/* PMU GRF Registers */
> +#define RK3399_PMUGRF_OS_REG2 0x308
> +#define RK3399_PMUGRF_DDRTYPE_SHIFT 13
> +#define RK3399_PMUGRF_DDRTYPE_MASK 7
> +#define RK3399_PMUGRF_DDRTYPE_DDR3 3
> +#define RK3399_PMUGRF_DDRTYPE_LPDDR2 5
> +#define RK3399_PMUGRF_DDRTYPE_LPDDR3 6
> +#define RK3399_PMUGRF_DDRTYPE_LPDDR4 7
> +
> +#endif
>
Looks good to me.
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
^ permalink raw reply
* [PATCH 1/7] i2c: i2c-gpio: move header to platform_data
From: James Hogan @ 2018-05-14 21:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514213719.o6ceftp2quem3s7f@ninjato>
On Mon, May 14, 2018 at 11:37:20PM +0200, Wolfram Sang wrote:
> > diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
> > index 4e79dbd54a33..fa75d75b5ba9 100644
> > --- a/arch/mips/alchemy/board-gpr.c
> > +++ b/arch/mips/alchemy/board-gpr.c
> > @@ -29,7 +29,7 @@
> > #include <linux/leds.h>
> > #include <linux/gpio.h>
> > #include <linux/i2c.h>
> > -#include <linux/i2c-gpio.h>
> > +#include <linux/platform_data/i2c-gpio.h>
> > #include <linux/gpio/machine.h>
> > #include <asm/bootinfo.h>
> > #include <asm/idle.h>
Acked-by: James Hogan <jhogan@kernel.org>
Cheers
James
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180514/3204a488/attachment.sig>
^ permalink raw reply
* [PATCH 1/7] i2c: i2c-gpio: move header to platform_data
From: Wolfram Sang @ 2018-05-14 21:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180419200015.15095-2-wsa@the-dreams.de>
> arch/arm/mach-ks8695/board-acs5k.c | 2 +-
> arch/arm/mach-sa1100/simpad.c | 2 +-
> arch/mips/alchemy/board-gpr.c | 2 +-
Those still need acks...
> diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
> index 937eb1d47e7b..ef835d82cdb9 100644
> --- a/arch/arm/mach-ks8695/board-acs5k.c
> +++ b/arch/arm/mach-ks8695/board-acs5k.c
> @@ -19,7 +19,7 @@
> #include <linux/gpio/machine.h>
> #include <linux/i2c.h>
> #include <linux/i2c-algo-bit.h>
> -#include <linux/i2c-gpio.h>
> +#include <linux/platform_data/i2c-gpio.h>
> #include <linux/platform_data/pca953x.h>
>
> #include <linux/mtd/mtd.h>
...
> diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
> index ace010479eb6..49a61e6f3c5f 100644
> --- a/arch/arm/mach-sa1100/simpad.c
> +++ b/arch/arm/mach-sa1100/simpad.c
> @@ -37,7 +37,7 @@
> #include <linux/input.h>
> #include <linux/gpio_keys.h>
> #include <linux/leds.h>
> -#include <linux/i2c-gpio.h>
> +#include <linux/platform_data/i2c-gpio.h>
>
> #include "generic.h"
>
> diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
> index 4e79dbd54a33..fa75d75b5ba9 100644
> --- a/arch/mips/alchemy/board-gpr.c
> +++ b/arch/mips/alchemy/board-gpr.c
> @@ -29,7 +29,7 @@
> #include <linux/leds.h>
> #include <linux/gpio.h>
> #include <linux/i2c.h>
> -#include <linux/i2c-gpio.h>
> +#include <linux/platform_data/i2c-gpio.h>
> #include <linux/gpio/machine.h>
> #include <asm/bootinfo.h>
> #include <asm/idle.h>
... and this was the shortened diff for those.
Greg, Russell, Ralf, James? Is it okay if I take this via my tree?
Thanks,
Wolfram
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180514/f3c37915/attachment.sig>
^ permalink raw reply
* [PATCH 12/12] of/platform: make the OF code aware of early platform drivers
From: Geert Uytterhoeven @ 2018-05-14 21:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180511162028.20616-13-brgl@bgdev.pl>
Hi Bartosz,
On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Check the relevant flag in the device node and skip the allocation
> part for devices that were populated early.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Thanks for your patch!
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -196,9 +197,17 @@ static struct platform_device *of_platform_device_create_pdata(
> of_node_test_and_set_flag(np, OF_POPULATED))
> return NULL;
>
> - dev = of_device_alloc(np, bus_id, parent);
> - if (!dev)
> - goto err_clear_flag;
> + if (of_node_check_flag(np, OF_POPULATED_EARLY)) {
> + dev = of_early_to_platform_device(np);
> + if (IS_ERR(dev))
> + goto err_clear_flag;
> +
> + of_device_init(dev, np, bus_id, parent);
> + } else {
> + dev = of_device_alloc(np, bus_id, parent);
> + if (!dev)
> + goto err_clear_flag;
> + }
The above may become cleaner if:
1. of_early_to_platform_device() would return NULL instead -ENOENT,
2. of_device_alloc() would be split in alloc and init phases, too.
Then you can do:
dev = of_node_check_flag(np, OF_POPULATED_EARLY)
? of_early_to_platform_device(np)
: __of_device_alloc(np, bus_id, parent);
if (!dev)
goto err_clear_flag;
of_device_init(dev, np, bus_id, parent);
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 09/12] platform/early: add an init section for early driver data
From: Geert Uytterhoeven @ 2018-05-14 21:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180511162028.20616-10-brgl@bgdev.pl>
Hi Bartosz,
On Fri, May 11, 2018 at 6:20 PM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> Provide a separate section in which pointers to early platform driver
> structs will be stored.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Thanks for your patch!
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -214,6 +214,16 @@
> #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
> #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
>
> +#ifdef CONFIG_EARLY_PLATFORM
> +#define EARLY_PLATFORM_DRIVERS_TABLE() \
> + . = ALIGN(8); \
Should this use STRUCT_ALIGN() instead?
> + VMLINUX_SYMBOL(__early_platform_drivers_table) = .; \
> + KEEP(*(__early_platform_drivers_table)) \
> + VMLINUX_SYMBOL(__early_platform_drivers_table_end) = .;
> +#else
> +#define EARLY_PLATFORM_DRIVERS_TABLE()
> +#endif
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox