Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/6] ARM: mx31moboard-smartbot: Remove camera support
From: Fabio Estevam @ 2016-12-26 12:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482756987-12414-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam@nxp.com>

Since commit c93cc61475ebbe6e66 ("[media] staging/media: remove deprecated
mx3 driver") the mx3 camera driver has been removed, so remove the camera
support from the board file as well.

Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/mach-imx/mx31moboard-smartbot.c | 64 --------------------------------
 1 file changed, 64 deletions(-)

diff --git a/arch/arm/mach-imx/mx31moboard-smartbot.c b/arch/arm/mach-imx/mx31moboard-smartbot.c
index 89fc35a..a598c0a 100644
--- a/arch/arm/mach-imx/mx31moboard-smartbot.c
+++ b/arch/arm/mach-imx/mx31moboard-smartbot.c
@@ -23,8 +23,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <media/soc_camera.h>
-
 #include "board-mx31moboard.h"
 #include "common.h"
 #include "devices-imx31.h"
@@ -56,65 +54,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-#define CAM_POWER	IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
-#define CAM_RST_B	IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
-
-static int smartbot_cam_power(struct device *dev, int on)
-{
-	gpio_set_value(CAM_POWER, !on);
-	return 0;
-}
-
-static int smartbot_cam_reset(struct device *dev)
-{
-	gpio_set_value(CAM_RST_B, 0);
-	udelay(100);
-	gpio_set_value(CAM_RST_B, 1);
-	return 0;
-}
-
-static struct i2c_board_info smartbot_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("mt9t031", 0x5d),
-	},
-};
-
-static struct soc_camera_link base_iclink = {
-	.bus_id		= 0,		/* Must match with the camera ID */
-	.power		= smartbot_cam_power,
-	.reset		= smartbot_cam_reset,
-	.board_info	= &smartbot_i2c_devices[0],
-	.i2c_adapter_id	= 0,
-};
-
-static struct platform_device smartbot_camera[] = {
-	{
-		.name	= "soc-camera-pdrv",
-		.id	= 0,
-		.dev	= {
-			.platform_data = &base_iclink,
-		},
-	},
-};
-
-static struct platform_device *smartbot_cameras[] __initdata = {
-	&smartbot_camera[0],
-};
-
-static int __init smartbot_cam_init(void)
-{
-	int ret = gpio_request(CAM_RST_B, "cam-reset");
-	if (ret)
-		return ret;
-	gpio_direction_output(CAM_RST_B, 1);
-	ret = gpio_request(CAM_POWER, "cam-standby");
-	if (ret)
-		return ret;
-	gpio_direction_output(CAM_POWER, 0);
-
-	return 0;
-}
-
 static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_ULPI,
@@ -201,7 +140,4 @@ void __init mx31moboard_smartbot_init(int board)
 	}
 
 	smartbot_resets_init();
-
-	smartbot_cam_init();
-	platform_add_devices(smartbot_cameras, ARRAY_SIZE(smartbot_cameras));
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/6] ARM: mx31moboard-marxbot: Remove camera support
From: Fabio Estevam @ 2016-12-26 12:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482756987-12414-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam@nxp.com>

Since commit c93cc61475ebbe6e66 ("[media] staging/media: remove deprecated
mx3 driver") the mx3 camera driver has been removed, so remove the camera
support from the board file as well.

Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/mach-imx/mx31moboard-marxbot.c | 81 ---------------------------------
 1 file changed, 81 deletions(-)

diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c
index 2e895a8..0281fd2 100644
--- a/arch/arm/mach-imx/mx31moboard-marxbot.c
+++ b/arch/arm/mach-imx/mx31moboard-marxbot.c
@@ -24,8 +24,6 @@
 
 #include <linux/usb/otg.h>
 
-#include <media/soc_camera.h>
-
 #include "common.h"
 #include "devices-imx31.h"
 #include "ehci.h"
@@ -143,82 +141,6 @@ static struct spi_board_info marxbot_spi_board_info[] __initdata = {
 	},
 };
 
-#define TURRETCAM_POWER	IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
-#define BASECAM_POWER	IOMUX_TO_GPIO(MX31_PIN_CSI_D5)
-#define TURRETCAM_RST_B	IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
-#define BASECAM_RST_B	IOMUX_TO_GPIO(MX31_PIN_CSI_D4)
-#define CAM_CHOICE	IOMUX_TO_GPIO(MX31_PIN_TXD2)
-
-static int marxbot_basecam_power(struct device *dev, int on)
-{
-	gpio_set_value(BASECAM_POWER, !on);
-	return 0;
-}
-
-static int marxbot_basecam_reset(struct device *dev)
-{
-	gpio_set_value(BASECAM_RST_B, 0);
-	udelay(100);
-	gpio_set_value(BASECAM_RST_B, 1);
-	return 0;
-}
-
-static struct i2c_board_info marxbot_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("mt9t031", 0x5d),
-	},
-};
-
-static struct soc_camera_link base_iclink = {
-	.bus_id		= 0,		/* Must match with the camera ID */
-	.power		= marxbot_basecam_power,
-	.reset		= marxbot_basecam_reset,
-	.board_info	= &marxbot_i2c_devices[0],
-	.i2c_adapter_id	= 0,
-};
-
-static struct platform_device marxbot_camera[] = {
-	{
-		.name	= "soc-camera-pdrv",
-		.id	= 0,
-		.dev	= {
-			.platform_data = &base_iclink,
-		},
-	},
-};
-
-static struct platform_device *marxbot_cameras[] __initdata = {
-	&marxbot_camera[0],
-};
-
-static int __init marxbot_cam_init(void)
-{
-	int ret = gpio_request(CAM_CHOICE, "cam-choice");
-	if (ret)
-		return ret;
-	gpio_direction_output(CAM_CHOICE, 0);
-
-	ret = gpio_request(BASECAM_RST_B, "basecam-reset");
-	if (ret)
-		return ret;
-	gpio_direction_output(BASECAM_RST_B, 1);
-	ret = gpio_request(BASECAM_POWER, "basecam-standby");
-	if (ret)
-		return ret;
-	gpio_direction_output(BASECAM_POWER, 0);
-
-	ret = gpio_request(TURRETCAM_RST_B, "turretcam-reset");
-	if (ret)
-		return ret;
-	gpio_direction_output(TURRETCAM_RST_B, 1);
-	ret = gpio_request(TURRETCAM_POWER, "turretcam-standby");
-	if (ret)
-		return ret;
-	gpio_direction_output(TURRETCAM_POWER, 0);
-
-	return 0;
-}
-
 #define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
 #define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
 #define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
@@ -356,9 +278,6 @@ void __init mx31moboard_marxbot_init(void)
 	spi_register_board_info(marxbot_spi_board_info,
 		ARRAY_SIZE(marxbot_spi_board_info));
 
-	marxbot_cam_init();
-	platform_add_devices(marxbot_cameras, ARRAY_SIZE(marxbot_cameras));
-
 	/* battery present pin */
 	gpio_request(IOMUX_TO_GPIO(MX31_PIN_LCS0), "bat-present");
 	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_LCS0));
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/6] ARM: mach-mx31_3ds: Remove camera support
From: Fabio Estevam @ 2016-12-26 12:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Fabio Estevam <fabio.estevam@nxp.com>

Since commit c93cc61475ebbe6e66 ("[media] staging/media: remove deprecated
mx3 driver") the mx3 camera driver has been removed, so remove the camera
support from the board file as well.

Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/mach-imx/mach-mx31_3ds.c | 145 --------------------------------------
 1 file changed, 145 deletions(-)

diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 12b8a52..ada29d0 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -26,16 +26,12 @@
 #include <linux/regulator/machine.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
-#include <linux/memblock.h>
-
-#include <media/soc_camera.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <asm/memblock.h>
 
 #include "3ds_debugboard.h"
 #include "common.h"
@@ -152,8 +148,6 @@ static int mx31_3ds_pins[] = {
 	MX31_PIN_CSI_MCLK__CSI_MCLK,
 	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
 	MX31_PIN_CSI_VSYNC__CSI_VSYNC,
-	MX31_PIN_CSI_D5__GPIO3_5, /* CMOS PWDN */
-	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
 	/* SSI */
 	MX31_PIN_STXD4__STXD4,
 	MX31_PIN_SRXD4__SRXD4,
@@ -162,98 +156,6 @@ static int mx31_3ds_pins[] = {
 };
 
 /*
- * Camera support
- */
-static phys_addr_t mx3_camera_base __initdata;
-#define MX31_3DS_CAMERA_BUF_SIZE SZ_8M
-
-#define MX31_3DS_GPIO_CAMERA_PW IOMUX_TO_GPIO(MX31_PIN_CSI_D5)
-#define MX31_3DS_GPIO_CAMERA_RST IOMUX_TO_GPIO(MX31_PIN_RI_DTE1)
-
-static struct gpio mx31_3ds_camera_gpios[] = {
-	{ MX31_3DS_GPIO_CAMERA_PW, GPIOF_OUT_INIT_HIGH, "camera-power" },
-	{ MX31_3DS_GPIO_CAMERA_RST, GPIOF_OUT_INIT_HIGH, "camera-reset" },
-};
-
-static const struct mx3_camera_pdata mx31_3ds_camera_pdata __initconst = {
-	.flags = MX3_CAMERA_DATAWIDTH_10,
-	.mclk_10khz = 2600,
-};
-
-static int __init mx31_3ds_init_camera(void)
-{
-	int dma, ret = -ENOMEM;
-	struct platform_device *pdev =
-		imx31_alloc_mx3_camera(&mx31_3ds_camera_pdata);
-
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	if (!mx3_camera_base)
-		goto err;
-
-	dma = dma_declare_coherent_memory(&pdev->dev,
-					mx3_camera_base, mx3_camera_base,
-					MX31_3DS_CAMERA_BUF_SIZE,
-					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-
-	if (!(dma & DMA_MEMORY_MAP))
-		goto err;
-
-	ret = platform_device_add(pdev);
-	if (ret)
-err:
-		platform_device_put(pdev);
-
-	return ret;
-}
-
-static int mx31_3ds_camera_power(struct device *dev, int on)
-{
-	/* enable or disable the camera */
-	pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
-	gpio_set_value(MX31_3DS_GPIO_CAMERA_PW, on ? 0 : 1);
-
-	if (!on)
-		goto out;
-
-	/* If enabled, give a reset impulse */
-	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 0);
-	msleep(20);
-	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 1);
-	msleep(100);
-
-out:
-	return 0;
-}
-
-static struct i2c_board_info mx31_3ds_i2c_camera = {
-	I2C_BOARD_INFO("ov2640", 0x30),
-};
-
-static struct regulator_bulk_data mx31_3ds_camera_regs[] = {
-	{ .supply = "cmos_vcore" },
-	{ .supply = "cmos_2v8" },
-};
-
-static struct soc_camera_link iclink_ov2640 = {
-	.bus_id		= 0,
-	.board_info	= &mx31_3ds_i2c_camera,
-	.i2c_adapter_id	= 0,
-	.power		= mx31_3ds_camera_power,
-	.regulators	= mx31_3ds_camera_regs,
-	.num_regulators	= ARRAY_SIZE(mx31_3ds_camera_regs),
-};
-
-static struct platform_device mx31_3ds_ov2640 = {
-	.name	= "soc-camera-pdrv",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &iclink_ov2640,
-	},
-};
-
-/*
  * FB support
  */
 static const struct fb_videomode fb_modedb[] = {
@@ -410,7 +312,6 @@ static struct regulator_init_data vmmc2_init = {
 
 static struct regulator_consumer_supply vmmc1_consumers[] = {
 	REGULATOR_SUPPLY("vcore", "spi0.0"),
-	REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
 };
 
 static struct regulator_init_data vmmc1_init = {
@@ -441,22 +342,6 @@ static struct regulator_init_data vgen_init = {
 	.consumer_supplies = vgen_consumers,
 };
 
-static struct regulator_consumer_supply vvib_consumers[] = {
-	REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
-};
-
-static struct regulator_init_data vvib_init = {
-	.constraints = {
-		.min_uV = 1300000,
-		.max_uV = 1300000,
-		.apply_uV = 1,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
-	.consumer_supplies = vvib_consumers,
-};
-
 static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
 	{
 		.id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
@@ -480,9 +365,6 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
 	}, {
 		.id = MC13783_REG_VGEN,  /* Power LCD */
 		.init_data = &vgen_init,
-	}, {
-		.id = MC13783_REG_VVIB,  /* Power CMOS */
-		.init_data = &vvib_init,
 	},
 };
 
@@ -688,10 +570,6 @@ static const struct imxi2c_platform_data mx31_3ds_i2c0_data __initconst = {
 	.bitrate = 100000,
 };
 
-static struct platform_device *devices[] __initdata = {
-	&mx31_3ds_ov2640,
-};
-
 static void __init mx31_3ds_init(void)
 {
 	imx31_soc_init();
@@ -723,14 +601,10 @@ static void __init mx31_3ds_init(void)
 
 static void __init mx31_3ds_late(void)
 {
-	int ret;
-
 	mx31_3ds_spi_devs[0].irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
 	spi_register_board_info(mx31_3ds_spi_devs,
 				ARRAY_SIZE(mx31_3ds_spi_devs));
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
 	mx31_3ds_usbotg_init();
 	if (otg_mode_host) {
 		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
@@ -751,17 +625,6 @@ static void __init mx31_3ds_late(void)
 		       "devices on the debug board are unusable.\n");
 
 	imx31_add_mxc_mmc(0, &sdhc1_pdata);
-
-	/* CSI */
-	/* Camera power: default - off */
-	ret = gpio_request_array(mx31_3ds_camera_gpios,
-				 ARRAY_SIZE(mx31_3ds_camera_gpios));
-	if (ret) {
-		pr_err("Failed to request camera gpios");
-		iclink_ov2640.power = NULL;
-	}
-
-	mx31_3ds_init_camera();
 }
 
 static void __init mx31_3ds_timer_init(void)
@@ -769,13 +632,6 @@ static void __init mx31_3ds_timer_init(void)
 	mx31_clocks_init(26000000);
 }
 
-static void __init mx31_3ds_reserve(void)
-{
-	/* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
-	mx3_camera_base = arm_memblock_steal(MX31_3DS_CAMERA_BUF_SIZE,
-					 MX31_3DS_CAMERA_BUF_SIZE);
-}
-
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -785,6 +641,5 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	.init_time	= mx31_3ds_timer_init,
 	.init_machine = mx31_3ds_init,
 	.init_late	= mx31_3ds_late,
-	.reserve = mx31_3ds_reserve,
 	.restart	= mxc_restart,
 MACHINE_END
-- 
2.7.4

^ permalink raw reply related

* [PATCH] rtc: armada38x: add __ro_after_init to armada38x_rtc_ops
From: Bhumika Goyal @ 2016-12-26 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

The object armada38x_rtc_ops of type rtc_class_ops structure is not
modified after getting initialized by armada38x_rtc_probe. Apart from
getting referenced in init it is also passed as an argument to the function
devm_rtc_device_register but this argument is of type const struct
rtc_class_ops *. Therefore add __ro_after_init to its declaration.

Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
 drivers/rtc/rtc-armada38x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 9a3f2a6..7883c7f 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -202,7 +202,7 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static struct rtc_class_ops armada38x_rtc_ops = {
+static struct rtc_class_ops armada38x_rtc_ops __ro_after_init = {
 	.read_time = armada38x_rtc_read_time,
 	.set_time = armada38x_rtc_set_time,
 	.read_alarm = armada38x_rtc_read_alarm,
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 4/4] clk: rockchip: add new pll-type for rk3328
From: Heiko Stuebner @ 2016-12-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482723930-5876-5-git-send-email-zhangqing@rock-chips.com>

Am Montag, 26. Dezember 2016, 11:45:30 CET schrieb Elaine Zhang:
> The rk3328's pll and clock are similar with rk3036's,
> it different with pll_mode_mask, the rk3328 soc
> pll mode only one bit(rk3036 soc have two bits)
> so these should be independent and separate from
> the series of rk3328s.
> 
> Changes in v3:
>   fix up the pll type pll_rk3328 description and use
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---

pll-specific code looks good now, but please make this patch before the clock 
controller in the series and move the 

@@ -130,6 +152,7 @@
 enum rockchip_pll_type {
        pll_rk3036,
        pll_rk3066,
+       pll_rk3328,
        pll_rk3399,
 };
 
from patch3 into this one.


Thanks
Heiko

PS: I will have some comments for the clock controller patch, but it's xmas, 
so that may take bit still.

^ permalink raw reply

* [PATCH v3 2/4] dt-bindings: add bindings for rk3328 clock controller
From: Heiko Stuebner @ 2016-12-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482723930-5876-3-git-send-email-zhangqing@rock-chips.com>

Hi Elaine,

Am Montag, 26. Dezember 2016, 11:45:28 CET schrieb Elaine Zhang:
> Add devicetree bindings for Rockchip cru which found on
> Rockchip SoCs.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  .../bindings/clock/rockchip,rk3328-cru.txt         | 57
> ++++++++++++++++++++++ 1 file changed, 57 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt new file
> mode 100644
> index 000000000000..20053494d49f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> @@ -0,0 +1,57 @@
> +* Rockchip RK3328 Clock and Reset Unit
> +
> +The RK3328 clock controller generates and supplies clock to various
> +controllers within the SoC and also implements a reset controller for SoC
> +peripherals.
> +
> +Required Properties:
> +
> +- compatible: should be "rockchip,rk3328-cru"
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +- #clock-cells: should be 1.
> +- #reset-cells: should be 1.
> +
> +Optional Properties:
> +
> +- rockchip,grf: phandle to the syscon managing the "general register files"
> +  If missing pll rates are not changeable, due to the missing pll lock
> status. +
> +Each clock is assigned an identifier and client nodes can use this
> identifier +to specify the clock which they consume. All available clocks
> are defined as +preprocessor macros in the dt-bindings/clock/rk3328-cru.h
> headers and can be +used in device tree sources. Similar macros exist for
> the reset sources in +these files.
> +
> +External clocks:
> +
> +There are several clocks that are generated outside the SoC. It is expected
> +that they are defined using standard clock bindings with following
> +clock-output-names:
> + - "xin24m" - crystal input - required,
> + - "clkin_i2s" - external I2S clock - optional,
> + - "gmac_clkin" - external GMAC clock - optional
> + - "phy_50m_out" - output clock of the pll in the mac phy
> +
> +Example: Clock controller node:
> +
> +	cru: clock-controller at ff440000 {
> +		compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";

Rob suggested dropping the "rockchip,cru" and "syscon" properties from the 
example and I definitly agree with that.

Otherwise look ok to me.


Heiko

^ permalink raw reply

* [PATCH] arm64: Do not include linux/uaccess.h from assembler files
From: Guenter Roeck @ 2016-12-26 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

Including linux/uaccess.h from assembler files in arm64 builds results
in the following build errors.

In file included from arm64/include/asm/asm-offsets.h:1:0,
                 from arch/arm64/include/asm/assembler.h:26,
		 from arch/arm64/include/asm/alternative.h:68,
		 from arch/arm64/kernel/entry.S

include/linux/sched/prio.h: Assembler messages:
include/linux/sched/prio.h:47: Error:
	unknown mnemonic `static' --
		`static inline long nice_to_rlimit(long nice)'
build/include/linux/sched/prio.h:48: Error:
	junk at end of line, first unrecognized character is `{'

[and many more]

If asm/uaccess.h is not included, many of the affected files fail to build
with errors such as the following.

arch/arm64/lib/copy_to_user.S: Assembler messages:
arch/arm64/lib/copy_to_user.S:66: Error:
	unknown mnemonic `uaccess_enable_not_uao' --
		`uaccess_enable_not_uao x3,x4'
arch/arm64/lib/copy_template.S:71: Error:
	unknown mnemonic `uao_user_alternative' --
		`uao_user_alternative 9998f,strb,st trb,tmp1w,dst,#1'

Either drop the include if unnecessary or, if needed, replace with
asm/uaccess.h.

Fixes: 7c0f6ba682b9 ("Replace <asm/uaccess.h> with <linux/uaccess.h> globally")
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 arch/arm64/kernel/entry.S       | 1 -
 arch/arm64/lib/clear_user.S     | 2 +-
 arch/arm64/lib/copy_from_user.S | 2 +-
 arch/arm64/lib/copy_in_user.S   | 2 +-
 arch/arm64/lib/copy_to_user.S   | 2 +-
 arch/arm64/mm/cache.S           | 2 +-
 arch/arm64/xen/hypercall.S      | 2 +-
 7 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index a7504f40d7ee..fb93f8c25ff0 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -31,7 +31,6 @@
 #include <asm/memory.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
-#include <linux/uaccess.h>
 #include <asm/unistd.h>
 
 /*
diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S
index add4a1334085..d7150e30438a 100644
--- a/arch/arm64/lib/clear_user.S
+++ b/arch/arm64/lib/clear_user.S
@@ -17,7 +17,7 @@
  */
 #include <linux/linkage.h>
 
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 	.text
 
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
index fd6cd05593f9..cfe13396085b 100644
--- a/arch/arm64/lib/copy_from_user.S
+++ b/arch/arm64/lib/copy_from_user.S
@@ -17,7 +17,7 @@
 #include <linux/linkage.h>
 
 #include <asm/cache.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy from user space to a kernel buffer (alignment handled by the hardware)
diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S
index d828540ded6f..718b1c4e2f85 100644
--- a/arch/arm64/lib/copy_in_user.S
+++ b/arch/arm64/lib/copy_in_user.S
@@ -19,7 +19,7 @@
 #include <linux/linkage.h>
 
 #include <asm/cache.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy from user space to user space (alignment handled by the hardware)
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
index 3e6ae2663b82..e99e31c9acac 100644
--- a/arch/arm64/lib/copy_to_user.S
+++ b/arch/arm64/lib/copy_to_user.S
@@ -17,7 +17,7 @@
 #include <linux/linkage.h>
 
 #include <asm/cache.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy to user space from a kernel buffer (alignment handled by the hardware)
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 17f422a4dc55..da9576932322 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -23,7 +23,7 @@
 #include <asm/assembler.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 /*
  *	flush_icache_range(start,end)
diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S
index 47cf3f9d89ff..b41aff25426d 100644
--- a/arch/arm64/xen/hypercall.S
+++ b/arch/arm64/xen/hypercall.S
@@ -49,7 +49,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 #include <xen/interface/xen.h>
 
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH] PCI: exynos: refactor exynos pcie driver
From: Alim Akhtar @ 2016-12-26  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e1f37a59-b633-7b9d-cc79-dbbb00a24cda@samsung.com>

Hello Jaehoon

On 12/26/2016 02:32 PM, Jaehoon Chung wrote:
> Hi Pankaj,
>
> On 12/23/2016 07:56 PM, Pankaj Dubey wrote:
>> From: Niyas Ahmed S T <niyas.ahmed@samsung.com>
>>
>> Currently Exynos PCIe driver is only supported for Exynos5440 SoC.
>> This patch does refactoring of Exynos PCIe driver to extend support
>> for other Exynos SoC.
>>
>> Following are the main changes done via this patch:
>> 1) It adds separate structs for memory, clock resources.
>> 2) It add exynos_pcie_ops struct which will allow us to support the
>> differences in resources in different Exynos SoC.
>
> It's nice to me for reusing this file.
> but after considering too many times, i decided not to use this file.
>
> I'm not sure what block base is..actually this pci-exynos.c is really black-box.
> (No one maintains this file, even Samsung didn't care.)
> Who is using this?
> If Someone can share the information about exynos5440, i can refactor everything.
> Otherwise, there are two solution..
>
> One is "adding the new pci-exynos.c" likes pci-exynos5433.c
> Other is "refactor this file" under assuming the each register's usage.
>
Its alway good to reuse code as far as possible.
I am yet to see the details of 5440, but since people are now going to 
support more Exynos variants, in my opinion, instead of adding 
pci-exynos5433.c, you can rename current pci-exynos.c to something like 
pci-exynos5440.c (only in case its too much changes needed to support 
5433/exynos7) and lets have a common pci-exynos.c where we can add 
exynos7/5433 and others SoCs, AFAIK at least exynos7 and 5433 has 
similar pci controller.
> I want to use the PHY generic Framework for EXYNOS PCIe.
>
I don't think you have an option here, you should use generic PHY APIs, 
otherwise phy drive should go to drivers/misc.
Other thoughts are welcome.

> If you or other guys really want to use the pci-exynos.c for other exynos,
> I will rework with PHY generic framework. Then i will resend the my patches as V2.
>
> One more thing..Does anyone know what the usage of block base is?
> Can i use that register as "syscon"?
>
> Best Regards,
> Jaehoon Chung
>
>>
>> No functional change intended.
>>
>> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
>> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
>> ---
>> This patch set is prepared on top of Krzysztof's for-next and
>> PCIe driver cleanup patch [1] by Jaehoon Chung.
>>
>> [1]: https://lkml.org/lkml/2016/12/19/44
>>
>>
>>   drivers/pci/host/pci-exynos.c | 346 ++++++++++++++++++++++++++----------------
>>   1 file changed, 217 insertions(+), 129 deletions(-)
>>
>> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
>> index 33562cf..2dc54f7 100644
>> --- a/drivers/pci/host/pci-exynos.c
>> +++ b/drivers/pci/host/pci-exynos.c
>> @@ -17,6 +17,7 @@
>>   #include <linux/interrupt.h>
>>   #include <linux/kernel.h>
>>   #include <linux/init.h>
>> +#include <linux/of_device.h>
>>   #include <linux/of_gpio.h>
>>   #include <linux/pci.h>
>>   #include <linux/platform_device.h>
>> @@ -28,16 +29,6 @@
>>
>>   #define to_exynos_pcie(x)	container_of(x, struct exynos_pcie, pp)
>>
>> -struct exynos_pcie {
>> -	struct pcie_port	pp;
>> -	void __iomem		*elbi_base;	/* DT 0th resource */
>> -	void __iomem		*phy_base;	/* DT 1st resource */
>> -	void __iomem		*block_base;	/* DT 2nd resource */
>> -	int			reset_gpio;
>> -	struct clk		*clk;
>> -	struct clk		*bus_clk;
>> -};
>> -
>>   /* PCIe ELBI registers */
>>   #define PCIE_IRQ_PULSE			0x000
>>   #define IRQ_INTA_ASSERT			BIT(0)
>> @@ -102,6 +93,122 @@ struct exynos_pcie {
>>   #define PCIE_PHY_TRSV3_PD_TSV		BIT(7)
>>   #define PCIE_PHY_TRSV3_LVCC		0x31c
>>
>> +struct exynos_pcie_mem_res {
>> +	void __iomem *elbi_base; /* DT 0th resource: PCIE CTRL */
>> +	void __iomem *phy_base; /* DT 1st resource: PHY CTRL */
>> +	void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */
>> +};
>> +
>> +struct exynos_pcie_clk_res {
>> +	struct clk *clk;
>> +	struct clk *bus_clk;
>> +};
>> +
>> +struct exynos_pcie {
>> +	struct pcie_port		pp;
>> +	struct exynos_pcie_mem_res	*mem_res;
>> +	struct exynos_pcie_clk_res	*clk_res;
>> +	const struct exynos_pcie_ops	*ops;
>> +	int				reset_gpio;
>> +};
>> +
>> +struct exynos_pcie_ops {
>> +	int (*get_mem_resources)(struct platform_device *pdev,
>> +			struct exynos_pcie *ep);
>> +	int (*get_clk_resources)(struct exynos_pcie *ep);
>> +	int (*init_clk_resources)(struct exynos_pcie *ep);
>> +	void (*deinit_clk_resources)(struct exynos_pcie *ep);
>> +};
>> +
>> +static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev,
>> +						struct exynos_pcie *ep)
>> +{
>> +	struct resource *res;
>> +	struct device *dev = ep->pp.dev;
>> +
>> +	ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL);
>> +	if (!ep->mem_res)
>> +		return -ENOMEM;
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	ep->mem_res->elbi_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->elbi_base))
>> +		return PTR_ERR(ep->mem_res->elbi_base);
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +	ep->mem_res->phy_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->phy_base))
>> +		return PTR_ERR(ep->mem_res->phy_base);
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> +	ep->mem_res->block_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->block_base))
>> +		return PTR_ERR(ep->mem_res->block_base);
>> +
>> +	return 0;
>> +}
>> +
>> +static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	struct device *dev = ep->pp.dev;
>> +
>> +	ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL);
>> +	if (!ep->clk_res)
>> +		return -ENOMEM;
>> +
>> +	ep->clk_res->clk = devm_clk_get(dev, "pcie");
>> +	if (IS_ERR(ep->clk_res->clk)) {
>> +		dev_err(dev, "Failed to get pcie rc clock\n");
>> +		return PTR_ERR(ep->clk_res->clk);
>> +	}
>> +
>> +	ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus");
>> +	if (IS_ERR(ep->clk_res->bus_clk)) {
>> +		dev_err(dev, "Failed to get pcie bus clock\n");
>> +		return PTR_ERR(ep->clk_res->bus_clk);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	struct device *dev = ep->pp.dev;
>> +	int ret;
>> +
>> +	ret = clk_prepare_enable(ep->clk_res->clk);
>> +	if (ret) {
>> +		dev_err(dev, "cannot enable pcie rc clock");
>> +		return ret;
>> +	}
>> +
>> +	ret = clk_prepare_enable(ep->clk_res->bus_clk);
>> +	if (ret) {
>> +		dev_err(dev, "cannot enable pcie bus clock");
>> +		goto err_bus_clk;
>> +	}
>> +
>> +	return 0;
>> +
>> +err_bus_clk:
>> +	clk_disable_unprepare(ep->clk_res->clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	clk_disable_unprepare(ep->clk_res->bus_clk);
>> +	clk_disable_unprepare(ep->clk_res->clk);
>> +}
>> +
>> +static const struct exynos_pcie_ops exynos5440_pcie_ops = {
>> +	.get_mem_resources	= exynos5440_pcie_get_mem_resources,
>> +	.get_clk_resources	= exynos5440_pcie_get_clk_resources,
>> +	.init_clk_resources	= exynos5440_pcie_init_clk_resources,
>> +	.deinit_clk_resources	= exynos5440_pcie_deinit_clk_resources,
>> +};
>> +
>>   static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
>>   {
>>   	writel(val, base + reg);
>> @@ -116,155 +223,155 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC);
>>   	if (on)
>>   		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>>   	else
>>   		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
>>   }
>>
>>   static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC);
>>   	if (on)
>>   		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>>   	else
>>   		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
>>   }
>>
>>   static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>>   	val &= ~PCIE_CORE_RESET_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_PWR_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET);
>>   }
>>
>>   static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>>   	val |= PCIE_CORE_RESET_ENABLE;
>>
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET);
>> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_MAC_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET);
>>   }
>>
>>   static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep)
>>   {
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_MAC_RESET);
>> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_GLOBAL_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET);
>>   }
>>
>>   static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep)
>>   {
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_GLOBAL_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_PWR_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_COMMON_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_CMN_REG);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSVREG_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSV_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET);
>>   }
>>
>>   static void exynos_pcie_power_on_phy(struct exynos_pcie *ep)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>>   	val &= ~PCIE_PHY_COMMON_PD_CMN;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>>   	val &= ~PCIE_PHY_TRSV0_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>>   	val &= ~PCIE_PHY_TRSV1_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>>   	val &= ~PCIE_PHY_TRSV2_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>>   	val &= ~PCIE_PHY_TRSV3_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>>   }
>>
>>   static void exynos_pcie_power_off_phy(struct exynos_pcie *ep)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>>   	val |= PCIE_PHY_COMMON_PD_CMN;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>>   	val |= PCIE_PHY_TRSV0_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>>   	val |= PCIE_PHY_TRSV1_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>>   	val |= PCIE_PHY_TRSV2_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>>
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>>   	val |= PCIE_PHY_TRSV3_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>>   }
>>
>>   static void exynos_pcie_init_phy(struct exynos_pcie *ep)
>>   {
>>   	/* DCC feedback control off */
>> -	exynos_pcie_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
>>
>>   	/* set TX/RX impedance */
>> -	exynos_pcie_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
>>
>>   	/* set 50Mhz PHY clock */
>> -	exynos_pcie_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
>> -	exynos_pcie_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
>>
>>   	/* set TX Differential output for lane 0 */
>> -	exynos_pcie_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
>>
>>   	/* set TX Pre-emphasis Level Control for lane 0 to minimum */
>> -	exynos_pcie_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
>>
>>   	/* set RX clock and data recovery bandwidth */
>> -	exynos_pcie_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
>>
>>   	/* change TX Pre-emphasis Level Control for lanes */
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
>>
>>   	/* set LVCC */
>> -	exynos_pcie_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
>>   }
>>
>>   static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
>> @@ -295,25 +402,27 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
>>   	exynos_pcie_init_phy(exynos_pcie);
>>
>>   	/* pulse for common reset */
>> -	exynos_pcie_writel(exynos_pcie->block_base, 1, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 1,
>> +				PCIE_PHY_COMMON_RESET);
>>   	udelay(500);
>> -	exynos_pcie_writel(exynos_pcie->block_base, 0, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 0,
>> +				PCIE_PHY_COMMON_RESET);
>>
>>   	exynos_pcie_deassert_core_reset(exynos_pcie);
>>   	dw_pcie_setup_rc(pp);
>>   	exynos_pcie_assert_reset(exynos_pcie);
>>
>>   	/* assert LTSSM enable */
>> -	exynos_pcie_writel(exynos_pcie->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
>> -			  PCIE_APP_LTSSM_ENABLE);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->elbi_base,
>> +			PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE);
>>
>>   	/* check if the link is up or not */
>>   	if (!dw_pcie_wait_for_link(pp))
>>   		return 0;
>>
>> -	while (exynos_pcie_readl(exynos_pcie->phy_base,
>> +	while (exynos_pcie_readl(exynos_pcie->mem_res->phy_base,
>>   				PCIE_PHY_PLL_LOCKED) == 0) {
>> -		val = exynos_pcie_readl(exynos_pcie->block_base,
>> +		val = exynos_pcie_readl(exynos_pcie->mem_res->block_base,
>>   				PCIE_PHY_PLL_LOCKED);
>>   		dev_info(dev, "PLL Locked: 0x%x\n", val);
>>   	}
>> @@ -325,8 +434,8 @@ static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
>>   {
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE);
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE);
>>   }
>>
>>   static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
>> @@ -336,7 +445,7 @@ static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
>>   	/* enable INTX interrupt */
>>   	val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
>>   		IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE);
>>   }
>>
>>   static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
>> @@ -363,9 +472,9 @@ static void exynos_pcie_msi_init(struct exynos_pcie *ep)
>>   	dw_pcie_msi_init(pp);
>>
>>   	/* enable MSI interrupt */
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_EN_LEVEL);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL);
>>   	val |= IRQ_MSI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_LEVEL);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL);
>>   }
>>
>>   static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
>> @@ -425,7 +534,8 @@ static int exynos_pcie_link_up(struct pcie_port *pp)
>>   	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
>>   	u32 val;
>>
>> -	val = exynos_pcie_readl(exynos_pcie->elbi_base, PCIE_ELBI_RDLH_LINKUP);
>> +	val = exynos_pcie_readl(exynos_pcie->mem_res->elbi_base,
>> +					PCIE_ELBI_RDLH_LINKUP);
>>   	if (val == PCIE_ELBI_LTSSM_ENABLE)
>>   		return 1;
>>
>> @@ -503,7 +613,6 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>>   	struct exynos_pcie *exynos_pcie;
>>   	struct pcie_port *pp;
>>   	struct device_node *np = dev->of_node;
>> -	struct resource *res;
>>   	int ret;
>>
>>   	exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
>> @@ -513,59 +622,37 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>>   	pp = &exynos_pcie->pp;
>>   	pp->dev = dev;
>>
>> -	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
>> -
>> -	exynos_pcie->clk = devm_clk_get(dev, "pcie");
>> -	if (IS_ERR(exynos_pcie->clk)) {
>> -		dev_err(dev, "Failed to get pcie rc clock\n");
>> -		return PTR_ERR(exynos_pcie->clk);
>> -	}
>> -	ret = clk_prepare_enable(exynos_pcie->clk);
>> -	if (ret)
>> -		return ret;
>> +	exynos_pcie->ops = (const struct exynos_pcie_ops *)
>> +				of_device_get_match_data(dev);
>>
>> -	exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
>> -	if (IS_ERR(exynos_pcie->bus_clk)) {
>> -		dev_err(dev, "Failed to get pcie bus clock\n");
>> -		ret = PTR_ERR(exynos_pcie->bus_clk);
>> -		goto fail_clk;
>> -	}
>> -	ret = clk_prepare_enable(exynos_pcie->bus_clk);
>> -	if (ret)
>> -		goto fail_clk;
>> +	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
>>
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -	exynos_pcie->elbi_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->elbi_base)) {
>> -		ret = PTR_ERR(exynos_pcie->elbi_base);
>> -		goto fail_bus_clk;
>> +	if (exynos_pcie->ops && exynos_pcie->ops->get_mem_resources) {
>> +		ret = exynos_pcie->ops->get_mem_resources(pdev, exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>   	}
>>
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> -	exynos_pcie->phy_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->phy_base)) {
>> -		ret = PTR_ERR(exynos_pcie->phy_base);
>> -		goto fail_bus_clk;
>> -	}
>> +	if (exynos_pcie->ops && exynos_pcie->ops->get_clk_resources) {
>> +		ret = exynos_pcie->ops->get_clk_resources(exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> -	exynos_pcie->block_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->block_base)) {
>> -		ret = PTR_ERR(exynos_pcie->block_base);
>> -		goto fail_bus_clk;
>> +		ret = exynos_pcie->ops->init_clk_resources(exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>   	}
>>
>>   	ret = exynos_add_pcie_port(exynos_pcie, pdev);
>>   	if (ret < 0)
>> -		goto fail_bus_clk;
>> +		goto fail_probe;
>>
>>   	platform_set_drvdata(pdev, exynos_pcie);
>>   	return 0;
>>
>> -fail_bus_clk:
>> -	clk_disable_unprepare(exynos_pcie->bus_clk);
>> -fail_clk:
>> -	clk_disable_unprepare(exynos_pcie->clk);
>> +fail_probe:
>> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
>> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>>   	return ret;
>>   }
>>
>> @@ -573,14 +660,15 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev)
>>   {
>>   	struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev);
>>
>> -	clk_disable_unprepare(exynos_pcie->bus_clk);
>> -	clk_disable_unprepare(exynos_pcie->clk);
>> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
>> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>>
>>   	return 0;
>>   }
>>
>>   static const struct of_device_id exynos_pcie_of_match[] = {
>> -	{ .compatible = "samsung,exynos5440-pcie", },
>> +	{	.compatible = "samsung,exynos5440-pcie",
>> +		.data = &exynos5440_pcie_ops },
>>   	{},
>>   };
>>
>>
>
>
>

^ permalink raw reply

* [PATCH 4/9] pinctrl: samsung: Use generic of_device_get_match_data helper
From: Krzysztof Kozlowski @ 2016-12-26  9:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CA+Ln22FfYkxJAOtpfr1UUai6vZej09NSZa6cz2cuO2aHN8Trmw@mail.gmail.com>

On Mon, Dec 26, 2016 at 02:44:26PM +0900, Tomasz Figa wrote:
> 2016-12-25 21:56 GMT+09:00 Krzysztof Kozlowski <krzk@kernel.org>:
> > On Fri, Dec 23, 2016 at 01:24:44PM +0100, Marek Szyprowski wrote:
> >> Replace custom code with generic helper.
> >>
> >> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> >> ---
> >>  drivers/pinctrl/samsung/pinctrl-samsung.c | 9 ++++-----
> >>  1 file changed, 4 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> >> index 4d9262051ff1..a6c2ea74e0f3 100644
> >> --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> >> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> >> @@ -27,6 +27,7 @@
> >>  #include <linux/err.h>
> >>  #include <linux/gpio.h>
> >>  #include <linux/irqdomain.h>
> >> +#include <linux/of_device.h>
> >>  #include <linux/spinlock.h>
> >>  #include <linux/syscore_ops.h>
> >>
> >> @@ -967,15 +968,13 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
> >>       return 0;
> >>  }
> >>
> >> -static const struct of_device_id samsung_pinctrl_dt_match[];
> >> -
> >>  /* retrieve the soc specific data */
> >>  static const struct samsung_pin_ctrl *
> >>  samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
> >>                            struct platform_device *pdev)
> >>  {
> >>       int id;
> >> -     const struct of_device_id *match;
> >> +     const struct samsung_pin_ctrl *match_data;
> >>       struct device_node *node = pdev->dev.of_node;
> >>       struct device_node *np;
> >>       const struct samsung_pin_bank_data *bdata;
> >> @@ -990,8 +989,8 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
> >>               dev_err(&pdev->dev, "failed to get alias id\n");
> >>               return ERR_PTR(-ENOENT);
> >>       }
> >> -     match = of_match_node(samsung_pinctrl_dt_match, node);
> >> -     ctrl = (struct samsung_pin_ctrl *)match->data + id;
> >> +     match_data = of_device_get_match_data(&pdev->dev);
> >> +     ctrl = match_data + id;
> >
> > Either you need a check for match_data != NULL or just remove match_data
> > and:
> >         ctrl = of_device_get_match_data();
> >         ctrl += id;
> >
> > Actually match_data can be removed even with the check for non-NULL...
> 
> I don't think this function can ever return NULL if the match array
> contains a non-NULL value for each compatible string and the driver
> can be probed only by DT.

Practically it cannot (or it should not) but defensive coding is a good
practice...

> But you still need to cast the match data pointer to the correct type
> and using a variable for it IMHO makes the code cleaner.

What do you mean by casting through variable? match_data and ctrl are
the same type so there is no change by intermediate variable. It just
obfuscates the code.

BR,
Krzysztof

^ permalink raw reply

* [RESEND 2/2] arm64: dts: Add dts files for Hisilicon Hi3660 SoC
From: Chen Feng @ 2016-12-26  9:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482744972-56622-1-git-send-email-puck.chen@hisilicon.com>

Add initial dtsi file to support Hisilicon Hi3660 SoC with
support of Octal core CPUs in two clusters(4 * A53 & 4 * A73).

Also add dts file to support HiKey960 development board which
based on Hi3660 SoC.
The output console is earlycon "earlycon=pl011,0xfdf05000".
And the con_init uart5 with a fixed clock, which already
configured at bootloader.

When clock is available, the uart5 will be modified.

Tested on HiKey960 Board.

Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
---
 arch/arm64/boot/dts/hisilicon/Makefile            |   1 +
 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts |  34 +++++
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi         | 156 ++++++++++++++++++++++
 3 files changed, 191 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660.dtsi

diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
index d5f43a0..b633b5d 100644
--- a/arch/arm64/boot/dts/hisilicon/Makefile
+++ b/arch/arm64/boot/dts/hisilicon/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+dtb-$(CONFIG_ARCH_HISI) += hi3660-hikey960.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
 
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
new file mode 100644
index 0000000..3d7aead
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -0,0 +1,34 @@
+/*
+ * dts file for Hisilicon HiKey960 Development Board
+ *
+ * Copyright (C) 2016, Hisilicon Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "hi3660.dtsi"
+
+/ {
+	model = "HiKey960";
+	compatible = "hisilicon,hi3660";
+
+	aliases {
+		serial5 = &uart5;       /* console UART */
+	};
+
+	chosen {
+		stdout-path = "serial5:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x00400000 0x0 0xBFE00000>;
+	};
+
+	soc {
+		uart5: uart at fdf05000 {
+			status = "ok";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
new file mode 100644
index 0000000..7f9805c
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -0,0 +1,156 @@
+/*
+ * dts file for Hisilicon Hi3660 SoC
+ *
+ * Copyright (C) 2016, Hisilicon Ltd.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "hisilicon,hi3660";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+				core1 {
+					cpu = <&cpu5>;
+				};
+				core2 {
+					cpu = <&cpu6>;
+				};
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+		};
+
+		cpu0: cpu at 0 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 1 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 2 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 3 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+		};
+
+		cpu4: cpu at 100 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
+
+		cpu5: cpu at 101 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x101>;
+			enable-method = "psci";
+		};
+
+		cpu6: cpu at 102 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x102>;
+			enable-method = "psci";
+		};
+
+		cpu7: cpu at 103 {
+			compatible = "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x103>;
+			enable-method = "psci";
+		};
+	};
+
+	gic: interrupt-controller at e82b0000 {
+		compatible = "arm,gic-400";
+		reg = <0x0 0xe82b1000 0 0x1000>, /* GICD */
+		      <0x0 0xe82b2000 0 0x2000>, /* GICC */
+		      <0x0 0xe82b4000 0 0x2000>, /* GICH */
+		      <0x0 0xe82b6000 0 0x2000>; /* GICV */
+		#address-cells = <0>;
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+		clock-frequency = <1920000>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		fixed_uart5: fixed_19_2M {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <19200000>;
+			clock-output-names = "fixed:uart5";
+		};
+
+		uart5: uart at fdf05000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfdf05000 0x0 0x1000>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&fixed_uart5 &fixed_uart5>;
+			clock-names = "uartclk", "apb_pclk";
+			status = "ok";
+		};
+	};
+};
-- 
1.9.1

^ permalink raw reply related

* [RESEND 1/2] document: dt: add binding for Hi3660 SoC
From: Chen Feng @ 2016-12-26  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

Add binding for hisilicon Hi3660 SoC and HiKey960 Board.

Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
---
 Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 3f81575..7cf2847 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -8,6 +8,10 @@ Hi6220 SoC
 Required root node properties:
 	- compatible = "hisilicon,hi6220";
 
+Hi3660 SoC
+Required root node properties:
+	- compatible = "hisilicon,hi3660";
+
 HiKey Board
 Required root node properties:
 	- compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220";
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 2/2] arm64: allwinner: Kconfig: add essential pinctrl driver for H5
From: Icenowy Zheng @ 2016-12-26  9:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161226093127.5525-1-icenowy@aosc.xyz>

H5 SoC has two pin controllers, one (in user manual called "CPUx") needs
a slightly advanced driver, and the other (called "CPUs") is just equal
to the on in H3, and the H3 driver can be just reused.

Select the two necessary pinctrl drivers when building kernel for
Allwinner SoCs.

Also add H5 in the option's description.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm64/Kconfig.platforms | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 715ef1256838..e11523d204b5 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -5,8 +5,11 @@ config ARCH_SUNXI
 	select GENERIC_IRQ_CHIP
 	select PINCTRL
 	select PINCTRL_SUN50I_A64
+	select PINCTRL_SUN50I_H5
+	select PINCTRL_SUN8I_H3_R
 	help
-	  This enables support for Allwinner sunxi based SoCs like the A64.
+	  This enables support for Allwinner sunxi based SoCs like the A64
+	  and H5.
 
 config ARCH_ALPINE
 	bool "Annapurna Labs Alpine platform"
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 1/2] drivers: pinctrl: add driver for Allwinner H5 SoC
From: Icenowy Zheng @ 2016-12-26  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Based on the Allwinner H5 datasheet and the pinctrl driver of the
backward-compatible H3 this introduces the pin multiplex assignments for
the H5 SoC.

H5 introduced some more pin functions (e.g. three more groups of TS
pins, and one more groups of SIM pins) than H3.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes since v1:
- Add dt-binding.

 .../bindings/pinctrl/allwinner,sunxi-pinctrl.txt   |   1 +
 drivers/pinctrl/sunxi/Kconfig                      |   4 +
 drivers/pinctrl/sunxi/Makefile                     |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c          | 551 +++++++++++++++++++++
 4 files changed, 557 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index c931fb1c01a6..2fd688c8dbdb 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -23,6 +23,7 @@ Required properties:
   "allwinner,sun8i-h3-pinctrl"
   "allwinner,sun8i-h3-r-pinctrl"
   "allwinner,sun50i-a64-pinctrl"
+  "allwinner,sun50i-h5-r-pinctrl"
   "nextthing,gr8-pinctrl"
 
 - reg: Should contain the register physical address and length for the
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index bff1ffc6f01e..e9c47e8b2ee0 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -76,4 +76,8 @@ config PINCTRL_SUN50I_A64
 	bool
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_H5
+	bool
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 95f93d0561fc..bab215d25440 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_A64)	+= pinctrl-sun50i-a64.o
 obj-$(CONFIG_PINCTRL_SUN8I_A83T)	+= pinctrl-sun8i-a83t.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
+obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c
new file mode 100644
index 000000000000..98f2a6ee7634
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c
@@ -0,0 +1,551 @@
+/*
+ * Allwinner H5 SoC pinctrl driver.
+ *
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on pinctrl-sun8i-h3.c, which is:
+ * Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
+ *
+ * Based on pinctrl-sun8i-a23.c, which is:
+ * Copyright (C) 2014 Chen-Yu Tsai <wens@csie.org>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun50i_h5_pins[] = {
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PA_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PA_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PA_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PA_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PA_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm0"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PA_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "sim"),		/* PWREN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PA_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "sim"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PA_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "sim"),		/* DATA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PA_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "sim"),		/* RST */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),	/* PA_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "sim"),		/* DET */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)),	/* PA_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "di"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)),	/* PA_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "di"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)),	/* PA_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* CS */
+		  SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)),	/* PA_EINT13 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)),	/* PA_EINT14 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* MOSI */
+		  SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)),	/* PA_EINT15 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* MISO */
+		  SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)),	/* PA_EINT16 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spdif"),		/* OUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)),	/* PA_EINT17 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* SYNC */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)),	/* PA_EINT18 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)),	/* PA_EINT19 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DOUT */
+		  SUNXI_FUNCTION(0x3, "sim"),		/* VPPEN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)),	/* PA_EINT20 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DIN */
+		  SUNXI_FUNCTION(0x3, "sim"),		/* VPPPP */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)),	/* PA_EINT21 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* MOSI */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
+		  SUNXI_FUNCTION(0x3, "spi0"),		/* MISO */
+		  SUNXI_FUNCTION(0x4, "mmc2")),		/* DS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE1 */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* CS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE0 */
+		  SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* CMD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* RB1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ2 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ3 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ4 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ5 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ6 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ7 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQS */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* RST */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXD3 */
+		  SUNXI_FUNCTION(0x3, "di"),		/* TX */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXD2 */
+		  SUNXI_FUNCTION(0x3, "di"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* ERR */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXD1 */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* SYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXD0 */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* DVLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXCK */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXCTL/RXDV */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* RXERR */
+		  SUNXI_FUNCTION(0x4, "ts2")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXD3 */
+		  SUNXI_FUNCTION(0x4, "ts2"),		/* D3 */
+		  SUNXI_FUNCTION(0x5, "ts3")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXD2 */
+		  SUNXI_FUNCTION(0x4, "ts2"),		/* D4 */
+		  SUNXI_FUNCTION(0x5, "ts3")),		/* ERR */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXD1 */
+		  SUNXI_FUNCTION(0x4, "ts2"),		/* D5 */
+		  SUNXI_FUNCTION(0x5, "ts3")),		/* SYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXD0 */
+		  SUNXI_FUNCTION(0x4, "ts2"),		/* D6 */
+		  SUNXI_FUNCTION(0x5, "ts3")),		/* DVLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* CRS */
+		  SUNXI_FUNCTION(0x4, "ts2"),		/* D7 */
+		  SUNXI_FUNCTION(0x5, "ts3")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXCK */
+		  SUNXI_FUNCTION(0x4, "sim")),		/* PWREN */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXCTL/TXEN */
+		  SUNXI_FUNCTION(0x4, "sim")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* TXERR */
+		  SUNXI_FUNCTION(0x4, "sim")),		/* DATA */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* CLKIN/COL */
+		  SUNXI_FUNCTION(0x4, "sim")),		/* RST */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac"),		/* MDC */
+		  SUNXI_FUNCTION(0x4, "sim")),		/* DET */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "emac")),		/* MDIO */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* PCLK */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* ERR */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* HSYNC */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* SYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* VSYNC */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* DVLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D0 */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D1 */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D2 */
+		  SUNXI_FUNCTION(0x3, "ts0")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D3 */
+		  SUNXI_FUNCTION(0x3, "ts0"),		/* D3 */
+		  SUNXI_FUNCTION(0x4, "ts1")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D4 */
+		  SUNXI_FUNCTION(0x3, "ts0"),		/* D4 */
+		  SUNXI_FUNCTION(0x4, "ts1")),		/* ERR */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D5 */
+		  SUNXI_FUNCTION(0x3, "ts0"),		/* D5 */
+		  SUNXI_FUNCTION(0x4, "ts1"),		/* SYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D6 */
+		  SUNXI_FUNCTION(0x3, "ts0"),		/* D6 */
+		  SUNXI_FUNCTION(0x4, "ts1")),		/* DVLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* D7 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D7 */
+		  SUNXI_FUNCTION(0x4, "ts1")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "i2c2")),		/* SCK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "i2c2")),		/* SDA */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "sim")),		/* VPPEN */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "sim")),		/* VPPPP */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* MS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* DI */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "uart0")),	/* TX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* DO */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION(0x3, "uart0")),	/* RX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* CK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out")),
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PG_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PG_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PG_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PG_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PG_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PG_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PG_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)),	/* PG_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)),	/* PG_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)),	/* PG_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* SYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)),	/* PG_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)),	/* PG_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* DOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)),	/* PG_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* DIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)),	/* PG_EINT13 */
+};
+
+static const struct sunxi_pinctrl_desc sun50i_h5_pinctrl_data = {
+	.pins = sun50i_h5_pins,
+	.npins = ARRAY_SIZE(sun50i_h5_pins),
+	.irq_banks = 2,
+	.irq_read_needs_mux = true
+};
+
+static int sun50i_h5_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev,
+				  &sun50i_h5_pinctrl_data);
+}
+
+static const struct of_device_id sun50i_h5_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun50i-h5-pinctrl", },
+	{}
+};
+
+static struct platform_driver sun50i_h5_pinctrl_driver = {
+	.probe	= sun50i_h5_pinctrl_probe,
+	.driver	= {
+		.name		= "sun50i-h5-pinctrl",
+		.of_match_table	= sun50i_h5_pinctrl_match,
+	},
+};
+builtin_platform_driver(sun50i_h5_pinctrl_driver);
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 00/14] ACPI platform MSI support and its example mbigen
From: majun (Euler7) @ 2016-12-26  9:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5860DB5D.40701@huawei.com>

Hi:

? 2016/12/26 16:57, majun (Euler7) ??:
> Hi Hanjun:
> 	This patch set works fine on my Hisilicon D05 board.
> Feel free to add

Based on the Patch 1/3, 2/3 of [PATCH V9 0/3] irqchip: qcom: Add IRQ combiner driver
from Agustin Vega-Frias

https://lwn.net/Articles/709222/

> 	Tested-by: Majun <majun258@huawei.com>
> 
> ? 2016/12/22 13:35, Hanjun Guo ??:
>> From: Hanjun Guo <hanjun.guo@linaro.org>
>>
>> v4 -> v5:
>> 	- Add mbigen support back with tested on with Agustin's patchset,
>> 	  and it's a good example of how ACPI platform MSI works
>> 	- rebased on top of lastest Linus tree (commit 52bce91 splice: reinstate SIGPIPE/EPIPE handling)
>>
>> v3 -> v4:
>>         - Drop mbi-gen patches to just submit platform msi support because
>>           will rebase mbi-gen patches on top of Agustin's patchset, and discusion
>>           is going there.
>>         - Add a patch to support device topology such as NC(named componant, paltform device)
>>           ->SMMU->ITS which suggested by Lorenzo;
>>         - rebased on top of Lorenzo's v9 of ACPI IORT ARM SMMU support;
>>         - rebased on top of 4.9-rc7
>>
>> v2 -> v3:
>>         - Drop RFC tag
>>         - Rebase against v4.9-rc2 and Lorenzo's v6 of ACPI IORT ARM SMMU support [1]
>>         - Add 3 cleanup patches (patch 1, 2, 3)
>>         - Drop arch_init call patch from last version
>>         - Introduce a callback for platform device to set msi domain
>>         - Introduce a new API to get paltform device's domain instead of
>>           reusing the PCI one in previous version
>>         - Add a patch to rework iort_node_get_id()
>>
>> [1]: http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1251993.html
>>
>> v1 -> v2:
>>         - Fix the bug of if multi Interrupt() resoures in single _PRS,
>>           we need to calculate all the irq numbers (I missed it in previous
>>           version);
>>         - Rebased on Marc's irq/irqchip-4.9 branch and Lorenzo's v5
>>           SMMU patches (also Robin's SMMu patches)
>>         - Add patch irqchip: mbigen: promote mbigen init.
>>
>> With platform msi support landed in the kernel, and the introduction
>> of IORT for GICv3 ITS (PCI MSI) and SMMU, the framework for platform msi
>> is ready, this patch set add few patches to enable the ACPI platform
>> msi support.
>>
>> For platform device connecting to ITS on arm platform, we have IORT
>> table with the named componant node to describe the mappings of paltform
>> device and ITS, so we can retrieve the dev id and find its parent
>> irqdomain (ITS) from IORT table (simlar with the ACPI ITS support).
>>
>> The fisrt 3 patches are cleanups;
>>
>> Patch 4,5 are refactoring its_pmsi_prepare() for both DT and ACPI
>> then retrieve the dev id from iort;
>>
>> Patch 6,7 to create platform msi domain to ACPI case which scanned
>> the MADT table;
>>
>> Patch 8,9,10,11 to setup the msi domain for platform device based
>> on IORT table.
>>
>> Patch 12,13,14 convert dt based mbigen driver to support ACPI.
>>
>> Teasted on Hisilicon D03/D05.
>>
>> Happy holidays!
>>
>> Thanks
>> Hanjun
>>
>> Hanjun Guo (12):
>>   ACPI: ARM64: IORT: minor cleanup for iort_match_node_callback()
>>   irqchip: gic-v3-its: keep the head file include in alphabetic order
>>   ACPI: ARM64: IORT: add missing comment for iort_dev_find_its_id()
>>   irqchip: gicv3-its: platform-msi: refactor its_pmsi_prepare()
>>   ACPI: platform-msi: retrieve dev id from IORT
>>   irqchip: gicv3-its: platform-msi: refactor its_pmsi_init() to prepare
>>     for ACPI
>>   irqchip: gicv3-its: platform-msi: scan MADT to create platform msi
>>     domain
>>   ACPI: ARM64: IORT: rework iort_node_get_id()
>>   ACPI: platform: setup MSI domain for ACPI based platform device
>>   ACPI: ARM64: IORT: rework iort_node_get_id() for NC->SMMU->ITS case
>>   msi: platform: make platform_msi_create_device_domain() ACPI aware
>>   irqchip: mbigen: Add ACPI support
>>
>> Kefeng Wang (2):
>>   irqchip: mbigen: drop module owner
>>   irqchip: mbigen: introduce mbigen_of_create_domain()
>>
>>  drivers/acpi/acpi_platform.c                  |  11 ++
>>  drivers/acpi/arm64/iort.c                     | 138 ++++++++++++++++++++------
>>  drivers/base/platform-msi.c                   |   3 +-
>>  drivers/base/platform.c                       |   3 +
>>  drivers/irqchip/irq-gic-v3-its-platform-msi.c | 106 +++++++++++++++-----
>>  drivers/irqchip/irq-gic-v3-its.c              |   3 +-
>>  drivers/irqchip/irq-mbigen.c                  | 109 ++++++++++++++++----
>>  include/linux/acpi_iort.h                     |  11 ++
>>  include/linux/platform_device.h               |   3 +
>>  9 files changed, 309 insertions(+), 78 deletions(-)
>>
> 
> 
> .
> 

^ permalink raw reply

* coresight: Problem caused by resetting enable_sink
From: Wangnan (F) @ 2016-12-26  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mathieu,

I meet problems caused by your commit d52c9750f150 ('coresight:
reset "enable_sink" flag when need be'). Not only the one I
posted in the previous patch.

My use case is a simple 'perf record -e cs_etm// ls'. It works
properly before this commit, and failed when allocating aux buffer
after your commit. I can't fully understand your code, but the
problem I meet seems caused by inappropriately reseting sink.

My device is connected like this (use two etfs):

Core0--+
Core1--+-- funnel0 --> etf0
Core2--|
Core3--+

Core0--+
Core1--+-- funnel1 --> etf1
Core2--|
Core3--+

Before running perf, two etfs are activated using sysfs
enable_sink interface.

During etm_setup_aux, coresight_get_enabled_sink() finds
etf0 for core0, and automatically deactivates it.

For core1, coresight_get_enabled_sink() returns etf1.
However, etf1 is not on the link of core1, so following
coresight_build_path() fails.

I guess your commit is based on the assumption that all
sinks are in the patch for each cores. Like this:


Core0--+
Core1--+-- funnel0 --> etf0 ++
Core2--|                     |            +--- etr
Core3--+                     |            |
                              + replicator +
Core0--+                     |            |
Core1--+-- funnel1 --> etf1 ++            +--- etb
Core2--|
Core3--+

But it is not true, at least for some hisilicon board.

I have to revert your patch to make CoreSight on my board
work. Please reconsider this patch, or please give some
suggestion if you think I misunderstood your patch.

Thank you.

^ permalink raw reply

* [PATCH] PCI: exynos: refactor exynos pcie driver
From: Jaehoon Chung @ 2016-12-26  9:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e1f37a59-b633-7b9d-cc79-dbbb00a24cda@samsung.com>

On 12/26/2016 06:02 PM, Jaehoon Chung wrote:
> Hi Pankaj,
> 
> On 12/23/2016 07:56 PM, Pankaj Dubey wrote:
>> From: Niyas Ahmed S T <niyas.ahmed@samsung.com>
>>
>> Currently Exynos PCIe driver is only supported for Exynos5440 SoC.
>> This patch does refactoring of Exynos PCIe driver to extend support
>> for other Exynos SoC.
>>
>> Following are the main changes done via this patch:
>> 1) It adds separate structs for memory, clock resources.
>> 2) It add exynos_pcie_ops struct which will allow us to support the
>> differences in resources in different Exynos SoC.
> 
> It's nice to me for reusing this file.
> but after considering too many times, i decided not to use this file.
> 
> I'm not sure what block base is..actually this pci-exynos.c is really black-box.
> (No one maintains this file, even Samsung didn't care.)
> Who is using this? 
> If Someone can share the information about exynos5440, i can refactor everything.
> Otherwise, there are two solution..
> 
> One is "adding the new pci-exynos.c" likes pci-exynos5433.c
> Other is "refactor this file" under assuming the each register's usage.
> 
> I want to use the PHY generic Framework for EXYNOS PCIe.
> 
> If you or other guys really want to use the pci-exynos.c for other exynos,
> I will rework with PHY generic framework. Then i will resend the my patches as V2.
> 
> One more thing..Does anyone know what the usage of block base is?
> Can i use that register as "syscon"?

One more..I sent the patches for RFC. Plz, check them. :)

https://lkml.org/lkml/2016/12/26/6

Best Regards,
Jaehoon Chung

> 
> Best Regards,
> Jaehoon Chung
> 
>>
>> No functional change intended.
>>
>> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
>> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
>> ---
>> This patch set is prepared on top of Krzysztof's for-next and
>> PCIe driver cleanup patch [1] by Jaehoon Chung.
>>
>> [1]: https://lkml.org/lkml/2016/12/19/44
>>
>>
>>  drivers/pci/host/pci-exynos.c | 346 ++++++++++++++++++++++++++----------------
>>  1 file changed, 217 insertions(+), 129 deletions(-)
>>
>> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
>> index 33562cf..2dc54f7 100644
>> --- a/drivers/pci/host/pci-exynos.c
>> +++ b/drivers/pci/host/pci-exynos.c
>> @@ -17,6 +17,7 @@
>>  #include <linux/interrupt.h>
>>  #include <linux/kernel.h>
>>  #include <linux/init.h>
>> +#include <linux/of_device.h>
>>  #include <linux/of_gpio.h>
>>  #include <linux/pci.h>
>>  #include <linux/platform_device.h>
>> @@ -28,16 +29,6 @@
>>  
>>  #define to_exynos_pcie(x)	container_of(x, struct exynos_pcie, pp)
>>  
>> -struct exynos_pcie {
>> -	struct pcie_port	pp;
>> -	void __iomem		*elbi_base;	/* DT 0th resource */
>> -	void __iomem		*phy_base;	/* DT 1st resource */
>> -	void __iomem		*block_base;	/* DT 2nd resource */
>> -	int			reset_gpio;
>> -	struct clk		*clk;
>> -	struct clk		*bus_clk;
>> -};
>> -
>>  /* PCIe ELBI registers */
>>  #define PCIE_IRQ_PULSE			0x000
>>  #define IRQ_INTA_ASSERT			BIT(0)
>> @@ -102,6 +93,122 @@ struct exynos_pcie {
>>  #define PCIE_PHY_TRSV3_PD_TSV		BIT(7)
>>  #define PCIE_PHY_TRSV3_LVCC		0x31c
>>  
>> +struct exynos_pcie_mem_res {
>> +	void __iomem *elbi_base; /* DT 0th resource: PCIE CTRL */
>> +	void __iomem *phy_base; /* DT 1st resource: PHY CTRL */
>> +	void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */
>> +};
>> +
>> +struct exynos_pcie_clk_res {
>> +	struct clk *clk;
>> +	struct clk *bus_clk;
>> +};
>> +
>> +struct exynos_pcie {
>> +	struct pcie_port		pp;
>> +	struct exynos_pcie_mem_res	*mem_res;
>> +	struct exynos_pcie_clk_res	*clk_res;
>> +	const struct exynos_pcie_ops	*ops;
>> +	int				reset_gpio;
>> +};
>> +
>> +struct exynos_pcie_ops {
>> +	int (*get_mem_resources)(struct platform_device *pdev,
>> +			struct exynos_pcie *ep);
>> +	int (*get_clk_resources)(struct exynos_pcie *ep);
>> +	int (*init_clk_resources)(struct exynos_pcie *ep);
>> +	void (*deinit_clk_resources)(struct exynos_pcie *ep);
>> +};
>> +
>> +static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev,
>> +						struct exynos_pcie *ep)
>> +{
>> +	struct resource *res;
>> +	struct device *dev = ep->pp.dev;
>> +
>> +	ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL);
>> +	if (!ep->mem_res)
>> +		return -ENOMEM;
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	ep->mem_res->elbi_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->elbi_base))
>> +		return PTR_ERR(ep->mem_res->elbi_base);
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +	ep->mem_res->phy_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->phy_base))
>> +		return PTR_ERR(ep->mem_res->phy_base);
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> +	ep->mem_res->block_base = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(ep->mem_res->block_base))
>> +		return PTR_ERR(ep->mem_res->block_base);
>> +
>> +	return 0;
>> +}
>> +
>> +static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	struct device *dev = ep->pp.dev;
>> +
>> +	ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL);
>> +	if (!ep->clk_res)
>> +		return -ENOMEM;
>> +
>> +	ep->clk_res->clk = devm_clk_get(dev, "pcie");
>> +	if (IS_ERR(ep->clk_res->clk)) {
>> +		dev_err(dev, "Failed to get pcie rc clock\n");
>> +		return PTR_ERR(ep->clk_res->clk);
>> +	}
>> +
>> +	ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus");
>> +	if (IS_ERR(ep->clk_res->bus_clk)) {
>> +		dev_err(dev, "Failed to get pcie bus clock\n");
>> +		return PTR_ERR(ep->clk_res->bus_clk);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	struct device *dev = ep->pp.dev;
>> +	int ret;
>> +
>> +	ret = clk_prepare_enable(ep->clk_res->clk);
>> +	if (ret) {
>> +		dev_err(dev, "cannot enable pcie rc clock");
>> +		return ret;
>> +	}
>> +
>> +	ret = clk_prepare_enable(ep->clk_res->bus_clk);
>> +	if (ret) {
>> +		dev_err(dev, "cannot enable pcie bus clock");
>> +		goto err_bus_clk;
>> +	}
>> +
>> +	return 0;
>> +
>> +err_bus_clk:
>> +	clk_disable_unprepare(ep->clk_res->clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep)
>> +{
>> +	clk_disable_unprepare(ep->clk_res->bus_clk);
>> +	clk_disable_unprepare(ep->clk_res->clk);
>> +}
>> +
>> +static const struct exynos_pcie_ops exynos5440_pcie_ops = {
>> +	.get_mem_resources	= exynos5440_pcie_get_mem_resources,
>> +	.get_clk_resources	= exynos5440_pcie_get_clk_resources,
>> +	.init_clk_resources	= exynos5440_pcie_init_clk_resources,
>> +	.deinit_clk_resources	= exynos5440_pcie_deinit_clk_resources,
>> +};
>> +
>>  static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
>>  {
>>  	writel(val, base + reg);
>> @@ -116,155 +223,155 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC);
>>  	if (on)
>>  		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>>  	else
>>  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
>>  }
>>  
>>  static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC);
>>  	if (on)
>>  		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>>  	else
>>  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
>>  }
>>  
>>  static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>>  	val &= ~PCIE_CORE_RESET_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_PWR_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET);
>>  }
>>  
>>  static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>>  	val |= PCIE_CORE_RESET_ENABLE;
>>  
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET);
>> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_MAC_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET);
>>  }
>>  
>>  static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep)
>>  {
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_MAC_RESET);
>> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_GLOBAL_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET);
>>  }
>>  
>>  static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep)
>>  {
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_GLOBAL_RESET);
>> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_PWR_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_COMMON_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_CMN_REG);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSVREG_RESET);
>> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSV_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET);
>> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET);
>>  }
>>  
>>  static void exynos_pcie_power_on_phy(struct exynos_pcie *ep)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>>  	val &= ~PCIE_PHY_COMMON_PD_CMN;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>>  	val &= ~PCIE_PHY_TRSV0_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>>  	val &= ~PCIE_PHY_TRSV1_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>>  	val &= ~PCIE_PHY_TRSV2_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>>  	val &= ~PCIE_PHY_TRSV3_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>>  }
>>  
>>  static void exynos_pcie_power_off_phy(struct exynos_pcie *ep)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>>  	val |= PCIE_PHY_COMMON_PD_CMN;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>>  	val |= PCIE_PHY_TRSV0_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>>  	val |= PCIE_PHY_TRSV1_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>>  	val |= PCIE_PHY_TRSV2_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>>  
>> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
>> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>>  	val |= PCIE_PHY_TRSV3_PD_TSV;
>> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>>  }
>>  
>>  static void exynos_pcie_init_phy(struct exynos_pcie *ep)
>>  {
>>  	/* DCC feedback control off */
>> -	exynos_pcie_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
>>  
>>  	/* set TX/RX impedance */
>> -	exynos_pcie_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
>>  
>>  	/* set 50Mhz PHY clock */
>> -	exynos_pcie_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
>> -	exynos_pcie_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
>>  
>>  	/* set TX Differential output for lane 0 */
>> -	exynos_pcie_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
>>  
>>  	/* set TX Pre-emphasis Level Control for lane 0 to minimum */
>> -	exynos_pcie_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
>>  
>>  	/* set RX clock and data recovery bandwidth */
>> -	exynos_pcie_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
>> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
>>  
>>  	/* change TX Pre-emphasis Level Control for lanes */
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
>> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
>>  
>>  	/* set LVCC */
>> -	exynos_pcie_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
>> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
>> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
>>  }
>>  
>>  static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
>> @@ -295,25 +402,27 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
>>  	exynos_pcie_init_phy(exynos_pcie);
>>  
>>  	/* pulse for common reset */
>> -	exynos_pcie_writel(exynos_pcie->block_base, 1, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 1,
>> +				PCIE_PHY_COMMON_RESET);
>>  	udelay(500);
>> -	exynos_pcie_writel(exynos_pcie->block_base, 0, PCIE_PHY_COMMON_RESET);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 0,
>> +				PCIE_PHY_COMMON_RESET);
>>  
>>  	exynos_pcie_deassert_core_reset(exynos_pcie);
>>  	dw_pcie_setup_rc(pp);
>>  	exynos_pcie_assert_reset(exynos_pcie);
>>  
>>  	/* assert LTSSM enable */
>> -	exynos_pcie_writel(exynos_pcie->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
>> -			  PCIE_APP_LTSSM_ENABLE);
>> +	exynos_pcie_writel(exynos_pcie->mem_res->elbi_base,
>> +			PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE);
>>  
>>  	/* check if the link is up or not */
>>  	if (!dw_pcie_wait_for_link(pp))
>>  		return 0;
>>  
>> -	while (exynos_pcie_readl(exynos_pcie->phy_base,
>> +	while (exynos_pcie_readl(exynos_pcie->mem_res->phy_base,
>>  				PCIE_PHY_PLL_LOCKED) == 0) {
>> -		val = exynos_pcie_readl(exynos_pcie->block_base,
>> +		val = exynos_pcie_readl(exynos_pcie->mem_res->block_base,
>>  				PCIE_PHY_PLL_LOCKED);
>>  		dev_info(dev, "PLL Locked: 0x%x\n", val);
>>  	}
>> @@ -325,8 +434,8 @@ static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
>>  {
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE);
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE);
>>  }
>>  
>>  static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
>> @@ -336,7 +445,7 @@ static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
>>  	/* enable INTX interrupt */
>>  	val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
>>  		IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE);
>>  }
>>  
>>  static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
>> @@ -363,9 +472,9 @@ static void exynos_pcie_msi_init(struct exynos_pcie *ep)
>>  	dw_pcie_msi_init(pp);
>>  
>>  	/* enable MSI interrupt */
>> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_EN_LEVEL);
>> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL);
>>  	val |= IRQ_MSI_ENABLE;
>> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_LEVEL);
>> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL);
>>  }
>>  
>>  static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
>> @@ -425,7 +534,8 @@ static int exynos_pcie_link_up(struct pcie_port *pp)
>>  	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
>>  	u32 val;
>>  
>> -	val = exynos_pcie_readl(exynos_pcie->elbi_base, PCIE_ELBI_RDLH_LINKUP);
>> +	val = exynos_pcie_readl(exynos_pcie->mem_res->elbi_base,
>> +					PCIE_ELBI_RDLH_LINKUP);
>>  	if (val == PCIE_ELBI_LTSSM_ENABLE)
>>  		return 1;
>>  
>> @@ -503,7 +613,6 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>>  	struct exynos_pcie *exynos_pcie;
>>  	struct pcie_port *pp;
>>  	struct device_node *np = dev->of_node;
>> -	struct resource *res;
>>  	int ret;
>>  
>>  	exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
>> @@ -513,59 +622,37 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>>  	pp = &exynos_pcie->pp;
>>  	pp->dev = dev;
>>  
>> -	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
>> -
>> -	exynos_pcie->clk = devm_clk_get(dev, "pcie");
>> -	if (IS_ERR(exynos_pcie->clk)) {
>> -		dev_err(dev, "Failed to get pcie rc clock\n");
>> -		return PTR_ERR(exynos_pcie->clk);
>> -	}
>> -	ret = clk_prepare_enable(exynos_pcie->clk);
>> -	if (ret)
>> -		return ret;
>> +	exynos_pcie->ops = (const struct exynos_pcie_ops *)
>> +				of_device_get_match_data(dev);
>>  
>> -	exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
>> -	if (IS_ERR(exynos_pcie->bus_clk)) {
>> -		dev_err(dev, "Failed to get pcie bus clock\n");
>> -		ret = PTR_ERR(exynos_pcie->bus_clk);
>> -		goto fail_clk;
>> -	}
>> -	ret = clk_prepare_enable(exynos_pcie->bus_clk);
>> -	if (ret)
>> -		goto fail_clk;
>> +	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
>>  
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -	exynos_pcie->elbi_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->elbi_base)) {
>> -		ret = PTR_ERR(exynos_pcie->elbi_base);
>> -		goto fail_bus_clk;
>> +	if (exynos_pcie->ops && exynos_pcie->ops->get_mem_resources) {
>> +		ret = exynos_pcie->ops->get_mem_resources(pdev, exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>  	}
>>  
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> -	exynos_pcie->phy_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->phy_base)) {
>> -		ret = PTR_ERR(exynos_pcie->phy_base);
>> -		goto fail_bus_clk;
>> -	}
>> +	if (exynos_pcie->ops && exynos_pcie->ops->get_clk_resources) {
>> +		ret = exynos_pcie->ops->get_clk_resources(exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>  
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> -	exynos_pcie->block_base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(exynos_pcie->block_base)) {
>> -		ret = PTR_ERR(exynos_pcie->block_base);
>> -		goto fail_bus_clk;
>> +		ret = exynos_pcie->ops->init_clk_resources(exynos_pcie);
>> +		if (ret)
>> +			return ret;
>>  	}
>>  
>>  	ret = exynos_add_pcie_port(exynos_pcie, pdev);
>>  	if (ret < 0)
>> -		goto fail_bus_clk;
>> +		goto fail_probe;
>>  
>>  	platform_set_drvdata(pdev, exynos_pcie);
>>  	return 0;
>>  
>> -fail_bus_clk:
>> -	clk_disable_unprepare(exynos_pcie->bus_clk);
>> -fail_clk:
>> -	clk_disable_unprepare(exynos_pcie->clk);
>> +fail_probe:
>> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
>> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>>  	return ret;
>>  }
>>  
>> @@ -573,14 +660,15 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev)
>>  {
>>  	struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev);
>>  
>> -	clk_disable_unprepare(exynos_pcie->bus_clk);
>> -	clk_disable_unprepare(exynos_pcie->clk);
>> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
>> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>>  
>>  	return 0;
>>  }
>>  
>>  static const struct of_device_id exynos_pcie_of_match[] = {
>> -	{ .compatible = "samsung,exynos5440-pcie", },
>> +	{	.compatible = "samsung,exynos5440-pcie",
>> +		.data = &exynos5440_pcie_ops },
>>  	{},
>>  };
>>  
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 

^ permalink raw reply

* [PATCH] PCI: exynos: refactor exynos pcie driver
From: Jaehoon Chung @ 2016-12-26  9:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482490587-13611-1-git-send-email-pankaj.dubey@samsung.com>

Hi Pankaj,

On 12/23/2016 07:56 PM, Pankaj Dubey wrote:
> From: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> 
> Currently Exynos PCIe driver is only supported for Exynos5440 SoC.
> This patch does refactoring of Exynos PCIe driver to extend support
> for other Exynos SoC.
> 
> Following are the main changes done via this patch:
> 1) It adds separate structs for memory, clock resources.
> 2) It add exynos_pcie_ops struct which will allow us to support the
> differences in resources in different Exynos SoC.

It's nice to me for reusing this file.
but after considering too many times, i decided not to use this file.

I'm not sure what block base is..actually this pci-exynos.c is really black-box.
(No one maintains this file, even Samsung didn't care.)
Who is using this? 
If Someone can share the information about exynos5440, i can refactor everything.
Otherwise, there are two solution..

One is "adding the new pci-exynos.c" likes pci-exynos5433.c
Other is "refactor this file" under assuming the each register's usage.

I want to use the PHY generic Framework for EXYNOS PCIe.

If you or other guys really want to use the pci-exynos.c for other exynos,
I will rework with PHY generic framework. Then i will resend the my patches as V2.

One more thing..Does anyone know what the usage of block base is?
Can i use that register as "syscon"?

Best Regards,
Jaehoon Chung

> 
> No functional change intended.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> ---
> This patch set is prepared on top of Krzysztof's for-next and
> PCIe driver cleanup patch [1] by Jaehoon Chung.
> 
> [1]: https://lkml.org/lkml/2016/12/19/44
> 
> 
>  drivers/pci/host/pci-exynos.c | 346 ++++++++++++++++++++++++++----------------
>  1 file changed, 217 insertions(+), 129 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index 33562cf..2dc54f7 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -17,6 +17,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/kernel.h>
>  #include <linux/init.h>
> +#include <linux/of_device.h>
>  #include <linux/of_gpio.h>
>  #include <linux/pci.h>
>  #include <linux/platform_device.h>
> @@ -28,16 +29,6 @@
>  
>  #define to_exynos_pcie(x)	container_of(x, struct exynos_pcie, pp)
>  
> -struct exynos_pcie {
> -	struct pcie_port	pp;
> -	void __iomem		*elbi_base;	/* DT 0th resource */
> -	void __iomem		*phy_base;	/* DT 1st resource */
> -	void __iomem		*block_base;	/* DT 2nd resource */
> -	int			reset_gpio;
> -	struct clk		*clk;
> -	struct clk		*bus_clk;
> -};
> -
>  /* PCIe ELBI registers */
>  #define PCIE_IRQ_PULSE			0x000
>  #define IRQ_INTA_ASSERT			BIT(0)
> @@ -102,6 +93,122 @@ struct exynos_pcie {
>  #define PCIE_PHY_TRSV3_PD_TSV		BIT(7)
>  #define PCIE_PHY_TRSV3_LVCC		0x31c
>  
> +struct exynos_pcie_mem_res {
> +	void __iomem *elbi_base; /* DT 0th resource: PCIE CTRL */
> +	void __iomem *phy_base; /* DT 1st resource: PHY CTRL */
> +	void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */
> +};
> +
> +struct exynos_pcie_clk_res {
> +	struct clk *clk;
> +	struct clk *bus_clk;
> +};
> +
> +struct exynos_pcie {
> +	struct pcie_port		pp;
> +	struct exynos_pcie_mem_res	*mem_res;
> +	struct exynos_pcie_clk_res	*clk_res;
> +	const struct exynos_pcie_ops	*ops;
> +	int				reset_gpio;
> +};
> +
> +struct exynos_pcie_ops {
> +	int (*get_mem_resources)(struct platform_device *pdev,
> +			struct exynos_pcie *ep);
> +	int (*get_clk_resources)(struct exynos_pcie *ep);
> +	int (*init_clk_resources)(struct exynos_pcie *ep);
> +	void (*deinit_clk_resources)(struct exynos_pcie *ep);
> +};
> +
> +static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev,
> +						struct exynos_pcie *ep)
> +{
> +	struct resource *res;
> +	struct device *dev = ep->pp.dev;
> +
> +	ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL);
> +	if (!ep->mem_res)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	ep->mem_res->elbi_base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(ep->mem_res->elbi_base))
> +		return PTR_ERR(ep->mem_res->elbi_base);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	ep->mem_res->phy_base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(ep->mem_res->phy_base))
> +		return PTR_ERR(ep->mem_res->phy_base);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> +	ep->mem_res->block_base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(ep->mem_res->block_base))
> +		return PTR_ERR(ep->mem_res->block_base);
> +
> +	return 0;
> +}
> +
> +static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep)
> +{
> +	struct device *dev = ep->pp.dev;
> +
> +	ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL);
> +	if (!ep->clk_res)
> +		return -ENOMEM;
> +
> +	ep->clk_res->clk = devm_clk_get(dev, "pcie");
> +	if (IS_ERR(ep->clk_res->clk)) {
> +		dev_err(dev, "Failed to get pcie rc clock\n");
> +		return PTR_ERR(ep->clk_res->clk);
> +	}
> +
> +	ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus");
> +	if (IS_ERR(ep->clk_res->bus_clk)) {
> +		dev_err(dev, "Failed to get pcie bus clock\n");
> +		return PTR_ERR(ep->clk_res->bus_clk);
> +	}
> +
> +	return 0;
> +}
> +
> +static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)
> +{
> +	struct device *dev = ep->pp.dev;
> +	int ret;
> +
> +	ret = clk_prepare_enable(ep->clk_res->clk);
> +	if (ret) {
> +		dev_err(dev, "cannot enable pcie rc clock");
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(ep->clk_res->bus_clk);
> +	if (ret) {
> +		dev_err(dev, "cannot enable pcie bus clock");
> +		goto err_bus_clk;
> +	}
> +
> +	return 0;
> +
> +err_bus_clk:
> +	clk_disable_unprepare(ep->clk_res->clk);
> +
> +	return ret;
> +}
> +
> +static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep)
> +{
> +	clk_disable_unprepare(ep->clk_res->bus_clk);
> +	clk_disable_unprepare(ep->clk_res->clk);
> +}
> +
> +static const struct exynos_pcie_ops exynos5440_pcie_ops = {
> +	.get_mem_resources	= exynos5440_pcie_get_mem_resources,
> +	.get_clk_resources	= exynos5440_pcie_get_clk_resources,
> +	.init_clk_resources	= exynos5440_pcie_init_clk_resources,
> +	.deinit_clk_resources	= exynos5440_pcie_deinit_clk_resources,
> +};
> +
>  static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
>  {
>  	writel(val, base + reg);
> @@ -116,155 +223,155 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC);
>  	if (on)
>  		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>  	else
>  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
>  }
>  
>  static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC);
>  	if (on)
>  		val |= PCIE_ELBI_SLV_DBI_ENABLE;
>  	else
>  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
>  }
>  
>  static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>  	val &= ~PCIE_CORE_RESET_ENABLE;
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_PWR_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET);
>  }
>  
>  static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
>  	val |= PCIE_CORE_RESET_ENABLE;
>  
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET);
> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_MAC_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET);
>  }
>  
>  static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep)
>  {
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_MAC_RESET);
> -	exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_GLOBAL_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET);
>  }
>  
>  static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep)
>  {
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_GLOBAL_RESET);
> -	exynos_pcie_writel(ep->elbi_base, 1, PCIE_PWR_RESET);
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_COMMON_RESET);
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_CMN_REG);
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSVREG_RESET);
> -	exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSV_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET);
> +	exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET);
>  }
>  
>  static void exynos_pcie_power_on_phy(struct exynos_pcie *ep)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>  	val &= ~PCIE_PHY_COMMON_PD_CMN;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>  	val &= ~PCIE_PHY_TRSV0_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>  	val &= ~PCIE_PHY_TRSV1_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>  	val &= ~PCIE_PHY_TRSV2_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>  	val &= ~PCIE_PHY_TRSV3_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>  }
>  
>  static void exynos_pcie_power_off_phy(struct exynos_pcie *ep)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
>  	val |= PCIE_PHY_COMMON_PD_CMN;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
>  	val |= PCIE_PHY_TRSV0_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
>  	val |= PCIE_PHY_TRSV1_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
>  	val |= PCIE_PHY_TRSV2_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
>  
> -	val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
> +	val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
>  	val |= PCIE_PHY_TRSV3_PD_TSV;
> -	exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
> +	exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
>  }
>  
>  static void exynos_pcie_init_phy(struct exynos_pcie *ep)
>  {
>  	/* DCC feedback control off */
> -	exynos_pcie_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
>  
>  	/* set TX/RX impedance */
> -	exynos_pcie_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
>  
>  	/* set 50Mhz PHY clock */
> -	exynos_pcie_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
> -	exynos_pcie_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
>  
>  	/* set TX Differential output for lane 0 */
> -	exynos_pcie_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
>  
>  	/* set TX Pre-emphasis Level Control for lane 0 to minimum */
> -	exynos_pcie_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
>  
>  	/* set RX clock and data recovery bandwidth */
> -	exynos_pcie_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
> -	exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
>  
>  	/* change TX Pre-emphasis Level Control for lanes */
> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
> -	exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
>  
>  	/* set LVCC */
> -	exynos_pcie_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
> -	exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
> +	exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
>  }
>  
>  static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
> @@ -295,25 +402,27 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
>  	exynos_pcie_init_phy(exynos_pcie);
>  
>  	/* pulse for common reset */
> -	exynos_pcie_writel(exynos_pcie->block_base, 1, PCIE_PHY_COMMON_RESET);
> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 1,
> +				PCIE_PHY_COMMON_RESET);
>  	udelay(500);
> -	exynos_pcie_writel(exynos_pcie->block_base, 0, PCIE_PHY_COMMON_RESET);
> +	exynos_pcie_writel(exynos_pcie->mem_res->block_base, 0,
> +				PCIE_PHY_COMMON_RESET);
>  
>  	exynos_pcie_deassert_core_reset(exynos_pcie);
>  	dw_pcie_setup_rc(pp);
>  	exynos_pcie_assert_reset(exynos_pcie);
>  
>  	/* assert LTSSM enable */
> -	exynos_pcie_writel(exynos_pcie->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
> -			  PCIE_APP_LTSSM_ENABLE);
> +	exynos_pcie_writel(exynos_pcie->mem_res->elbi_base,
> +			PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE);
>  
>  	/* check if the link is up or not */
>  	if (!dw_pcie_wait_for_link(pp))
>  		return 0;
>  
> -	while (exynos_pcie_readl(exynos_pcie->phy_base,
> +	while (exynos_pcie_readl(exynos_pcie->mem_res->phy_base,
>  				PCIE_PHY_PLL_LOCKED) == 0) {
> -		val = exynos_pcie_readl(exynos_pcie->block_base,
> +		val = exynos_pcie_readl(exynos_pcie->mem_res->block_base,
>  				PCIE_PHY_PLL_LOCKED);
>  		dev_info(dev, "PLL Locked: 0x%x\n", val);
>  	}
> @@ -325,8 +434,8 @@ static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
>  {
>  	u32 val;
>  
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE);
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE);
>  }
>  
>  static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
> @@ -336,7 +445,7 @@ static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
>  	/* enable INTX interrupt */
>  	val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
>  		IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE);
>  }
>  
>  static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
> @@ -363,9 +472,9 @@ static void exynos_pcie_msi_init(struct exynos_pcie *ep)
>  	dw_pcie_msi_init(pp);
>  
>  	/* enable MSI interrupt */
> -	val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_EN_LEVEL);
> +	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL);
>  	val |= IRQ_MSI_ENABLE;
> -	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_LEVEL);
> +	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL);
>  }
>  
>  static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
> @@ -425,7 +534,8 @@ static int exynos_pcie_link_up(struct pcie_port *pp)
>  	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
>  	u32 val;
>  
> -	val = exynos_pcie_readl(exynos_pcie->elbi_base, PCIE_ELBI_RDLH_LINKUP);
> +	val = exynos_pcie_readl(exynos_pcie->mem_res->elbi_base,
> +					PCIE_ELBI_RDLH_LINKUP);
>  	if (val == PCIE_ELBI_LTSSM_ENABLE)
>  		return 1;
>  
> @@ -503,7 +613,6 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>  	struct exynos_pcie *exynos_pcie;
>  	struct pcie_port *pp;
>  	struct device_node *np = dev->of_node;
> -	struct resource *res;
>  	int ret;
>  
>  	exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
> @@ -513,59 +622,37 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
>  	pp = &exynos_pcie->pp;
>  	pp->dev = dev;
>  
> -	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
> -
> -	exynos_pcie->clk = devm_clk_get(dev, "pcie");
> -	if (IS_ERR(exynos_pcie->clk)) {
> -		dev_err(dev, "Failed to get pcie rc clock\n");
> -		return PTR_ERR(exynos_pcie->clk);
> -	}
> -	ret = clk_prepare_enable(exynos_pcie->clk);
> -	if (ret)
> -		return ret;
> +	exynos_pcie->ops = (const struct exynos_pcie_ops *)
> +				of_device_get_match_data(dev);
>  
> -	exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
> -	if (IS_ERR(exynos_pcie->bus_clk)) {
> -		dev_err(dev, "Failed to get pcie bus clock\n");
> -		ret = PTR_ERR(exynos_pcie->bus_clk);
> -		goto fail_clk;
> -	}
> -	ret = clk_prepare_enable(exynos_pcie->bus_clk);
> -	if (ret)
> -		goto fail_clk;
> +	exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
>  
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	exynos_pcie->elbi_base = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(exynos_pcie->elbi_base)) {
> -		ret = PTR_ERR(exynos_pcie->elbi_base);
> -		goto fail_bus_clk;
> +	if (exynos_pcie->ops && exynos_pcie->ops->get_mem_resources) {
> +		ret = exynos_pcie->ops->get_mem_resources(pdev, exynos_pcie);
> +		if (ret)
> +			return ret;
>  	}
>  
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -	exynos_pcie->phy_base = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(exynos_pcie->phy_base)) {
> -		ret = PTR_ERR(exynos_pcie->phy_base);
> -		goto fail_bus_clk;
> -	}
> +	if (exynos_pcie->ops && exynos_pcie->ops->get_clk_resources) {
> +		ret = exynos_pcie->ops->get_clk_resources(exynos_pcie);
> +		if (ret)
> +			return ret;
>  
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> -	exynos_pcie->block_base = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(exynos_pcie->block_base)) {
> -		ret = PTR_ERR(exynos_pcie->block_base);
> -		goto fail_bus_clk;
> +		ret = exynos_pcie->ops->init_clk_resources(exynos_pcie);
> +		if (ret)
> +			return ret;
>  	}
>  
>  	ret = exynos_add_pcie_port(exynos_pcie, pdev);
>  	if (ret < 0)
> -		goto fail_bus_clk;
> +		goto fail_probe;
>  
>  	platform_set_drvdata(pdev, exynos_pcie);
>  	return 0;
>  
> -fail_bus_clk:
> -	clk_disable_unprepare(exynos_pcie->bus_clk);
> -fail_clk:
> -	clk_disable_unprepare(exynos_pcie->clk);
> +fail_probe:
> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>  	return ret;
>  }
>  
> @@ -573,14 +660,15 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev)
>  {
>  	struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev);
>  
> -	clk_disable_unprepare(exynos_pcie->bus_clk);
> -	clk_disable_unprepare(exynos_pcie->clk);
> +	if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources)
> +		exynos_pcie->ops->deinit_clk_resources(exynos_pcie);
>  
>  	return 0;
>  }
>  
>  static const struct of_device_id exynos_pcie_of_match[] = {
> -	{ .compatible = "samsung,exynos5440-pcie", },
> +	{	.compatible = "samsung,exynos5440-pcie",
> +		.data = &exynos5440_pcie_ops },
>  	{},
>  };
>  
> 

^ permalink raw reply

* [PATCH v5 14/14] irqchip: mbigen: Add ACPI support
From: majun (Euler7) @ 2016-12-26  9:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482384922-21507-15-git-send-email-guohanjun@huawei.com>

Hi hanjun?

? 2016/12/22 13:35, Hanjun Guo ??:
> From: Hanjun Guo <hanjun.guo@linaro.org>
> 
> With the preparation of platform msi support and interrupt producer
> in DSDT, we can add mbigen ACPI support now.
> 
> We are using _PRS methd to indicate number of irq pins instead
> of num_pins in DT to avoid _DSD usage in this case.
> 
> For mbi-gen,
>     Device(MBI0) {
>           Name(_HID, "HISI0152")
>           Name(_UID, Zero)
>           Name(_CRS, ResourceTemplate() {
>                   Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
>           })
> 
>           Name (_PRS, ResourceTemplate() {
> 		  Interrupt(ResourceProducer,...) {12,14,....}
>           })
>     }
> 
> For devices,
> 
>    Device(COM0) {
>           Name(_HID, "ACPIIDxx")
>           Name(_UID, Zero)
>           Name(_CRS, ResourceTemplate() {
>                  Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
> 		 Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12}
>           })
>     }
> 
> With the helpe of platform msi and interrupt producer, then devices
> will get the virq from mbi-gen's irqdomain.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ma Jun <majun258@huawei.com>
> ---
>  drivers/irqchip/irq-mbigen.c | 70 ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 67 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
> index 4e11da5..17d35fa 100644
> --- a/drivers/irqchip/irq-mbigen.c
> +++ b/drivers/irqchip/irq-mbigen.c
> @@ -16,6 +16,7 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <linux/acpi.h>
>  #include <linux/interrupt.h>
>  #include <linux/irqchip.h>
>  #include <linux/module.h>
> @@ -180,7 +181,7 @@ static int mbigen_domain_translate(struct irq_domain *d,
>  				    unsigned long *hwirq,
>  				    unsigned int *type)
>  {
> -	if (is_of_node(fwspec->fwnode)) {
> +	if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) {
>  		if (fwspec->param_count != 2)
>  			return -EINVAL;
>  
> @@ -271,6 +272,54 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +#ifdef CONFIG_ACPI
> +static acpi_status mbigen_acpi_process_resource(struct acpi_resource *ares,
> +					     void *context)
> +{
> +	struct acpi_resource_extended_irq *ext_irq;
> +	u32 *num_irqs = context;
> +
> +	switch (ares->type) {
> +	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
> +		ext_irq = &ares->data.extended_irq;
> +		*num_irqs += ext_irq->interrupt_count;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +static int mbigen_acpi_create_domain(struct platform_device *pdev,
> +				     struct mbigen_device *mgn_chip)
> +{
> +	struct irq_domain *domain;
> +	u32 num_msis = 0;
> +	acpi_status status;
> +
> +	status = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), METHOD_NAME__PRS,
> +				     mbigen_acpi_process_resource, &num_msis);
> +        if (ACPI_FAILURE(status) || num_msis == 0)
> +		return -EINVAL;
> +
> +	domain = platform_msi_create_device_domain(&pdev->dev, num_msis,
> +						   mbigen_write_msg,
> +						   &mbigen_domain_ops,
> +						   mgn_chip);
> +	if (!domain)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +#else
> +static int mbigen_acpi_create_domain(struct platform_device *pdev,
> +				     struct mbigen_device *mgn_chip)
> +{
> +	return -ENODEV;
> +}
> +#endif
> +
>  static int mbigen_device_probe(struct platform_device *pdev)
>  {
>  	struct mbigen_device *mgn_chip;
> @@ -288,9 +337,17 @@ static int mbigen_device_probe(struct platform_device *pdev)
>  	if (IS_ERR(mgn_chip->base))
>  		return PTR_ERR(mgn_chip->base);
>  
> -	err = mbigen_of_create_domain(pdev, mgn_chip);
> -	if (err)
> +	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
> +		err = mbigen_of_create_domain(pdev, mgn_chip);
> +	else if (ACPI_COMPANION(&pdev->dev))
> +		err = mbigen_acpi_create_domain(pdev, mgn_chip);
> +	else
> +		err = -EINVAL;
> +
> +	if (err) {
> +		dev_err(&pdev->dev, "Failed to create mbi-gen@%p irqdomain", mgn_chip->base);
>  		return err;
> +	}
>  
>  	platform_set_drvdata(pdev, mgn_chip);
>  	return 0;
> @@ -302,10 +359,17 @@ static int mbigen_device_probe(struct platform_device *pdev)
>  };
>  MODULE_DEVICE_TABLE(of, mbigen_of_match);
>  
> +static const struct acpi_device_id mbigen_acpi_match[] = {
> +        { "HISI0152", 0 },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match);
> +
>  static struct platform_driver mbigen_platform_driver = {
>  	.driver = {
>  		.name		= "Hisilicon MBIGEN-V2",
>  		.of_match_table	= mbigen_of_match,
> +		.acpi_match_table = ACPI_PTR(mbigen_acpi_match),
>  	},
>  	.probe			= mbigen_device_probe,
>  };
> 
Reviewed-by: MaJun <majun258@huawei.com>

^ permalink raw reply

* [PATCH v5 13/14] irqchip: mbigen: introduce mbigen_of_create_domain()
From: majun (Euler7) @ 2016-12-26  8:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482384922-21507-14-git-send-email-guohanjun@huawei.com>

Hi hanjun?

? 2016/12/22 13:35, Hanjun Guo ??:
> From: Kefeng Wang <wangkefeng.wang@huawei.com>
> 
> Introduce mbigen_of_create_domain() to consolidate OF related
> code and prepare for ACPI later, no funtional change.
> 
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ma Jun <majun258@huawei.com>
> ---
>  drivers/irqchip/irq-mbigen.c | 42 +++++++++++++++++++++++++++---------------
>  1 file changed, 27 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
> index c01ab41..4e11da5 100644
> --- a/drivers/irqchip/irq-mbigen.c
> +++ b/drivers/irqchip/irq-mbigen.c
> @@ -236,27 +236,15 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
>  	.free		= irq_domain_free_irqs_common,
>  };
>  
> -static int mbigen_device_probe(struct platform_device *pdev)
> +static int mbigen_of_create_domain(struct platform_device *pdev,
> +				   struct mbigen_device *mgn_chip)
>  {
> -	struct mbigen_device *mgn_chip;
> +	struct device *parent;
>  	struct platform_device *child;
>  	struct irq_domain *domain;
>  	struct device_node *np;
> -	struct device *parent;
> -	struct resource *res;
>  	u32 num_pins;
>  
> -	mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
> -	if (!mgn_chip)
> -		return -ENOMEM;
> -
> -	mgn_chip->pdev = pdev;
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	mgn_chip->base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(mgn_chip->base))
> -		return PTR_ERR(mgn_chip->base);
> -
>  	for_each_child_of_node(pdev->dev.of_node, np) {
>  		if (!of_property_read_bool(np, "interrupt-controller"))
>  			continue;
> @@ -280,6 +268,30 @@ static int mbigen_device_probe(struct platform_device *pdev)
>  			return -ENOMEM;
>  	}
>  
> +	return 0;
> +}
> +
> +static int mbigen_device_probe(struct platform_device *pdev)
> +{
> +	struct mbigen_device *mgn_chip;
> +	struct resource *res;
> +	int err;
> +
> +	mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
> +	if (!mgn_chip)
> +		return -ENOMEM;
> +
> +	mgn_chip->pdev = pdev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mgn_chip->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
> +	if (IS_ERR(mgn_chip->base))
> +		return PTR_ERR(mgn_chip->base);
> +
> +	err = mbigen_of_create_domain(pdev, mgn_chip);
> +	if (err)
> +		return err;
> +
>  	platform_set_drvdata(pdev, mgn_chip);
>  	return 0;
>  }
> 
Reviewed-by: MaJun <majun258@huawei.com>

^ permalink raw reply

* [PATCH v5 12/14] irqchip: mbigen: drop module owner
From: majun (Euler7) @ 2016-12-26  8:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482384922-21507-13-git-send-email-guohanjun@huawei.com>

Hi hanjun?

? 2016/12/22 13:35, Hanjun Guo ??:
> From: Kefeng Wang <wangkefeng.wang@huawei.com>
> 
> Module owner will be set by driver core, so drop it.
> 
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ma Jun <majun258@huawei.com>
> ---
>  drivers/irqchip/irq-mbigen.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
> index 03b79b0..c01ab41 100644
> --- a/drivers/irqchip/irq-mbigen.c
> +++ b/drivers/irqchip/irq-mbigen.c
> @@ -293,7 +293,6 @@ static int mbigen_device_probe(struct platform_device *pdev)
>  static struct platform_driver mbigen_platform_driver = {
>  	.driver = {
>  		.name		= "Hisilicon MBIGEN-V2",
> -		.owner		= THIS_MODULE,
>  		.of_match_table	= mbigen_of_match,
>  	},
>  	.probe			= mbigen_device_probe,
> 

Reviewed-by: MaJun <majun258@huawei.com>

^ permalink raw reply

* [PATCH v5 00/14] ACPI platform MSI support and its example mbigen
From: majun (Euler7) @ 2016-12-26  8:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482384922-21507-1-git-send-email-guohanjun@huawei.com>

Hi Hanjun:
	This patch set works fine on my Hisilicon D05 board.
Feel free to add
	Tested-by: Majun <majun258@huawei.com>

? 2016/12/22 13:35, Hanjun Guo ??:
> From: Hanjun Guo <hanjun.guo@linaro.org>
> 
> v4 -> v5:
> 	- Add mbigen support back with tested on with Agustin's patchset,
> 	  and it's a good example of how ACPI platform MSI works
> 	- rebased on top of lastest Linus tree (commit 52bce91 splice: reinstate SIGPIPE/EPIPE handling)
> 
> v3 -> v4:
>         - Drop mbi-gen patches to just submit platform msi support because
>           will rebase mbi-gen patches on top of Agustin's patchset, and discusion
>           is going there.
>         - Add a patch to support device topology such as NC(named componant, paltform device)
>           ->SMMU->ITS which suggested by Lorenzo;
>         - rebased on top of Lorenzo's v9 of ACPI IORT ARM SMMU support;
>         - rebased on top of 4.9-rc7
> 
> v2 -> v3:
>         - Drop RFC tag
>         - Rebase against v4.9-rc2 and Lorenzo's v6 of ACPI IORT ARM SMMU support [1]
>         - Add 3 cleanup patches (patch 1, 2, 3)
>         - Drop arch_init call patch from last version
>         - Introduce a callback for platform device to set msi domain
>         - Introduce a new API to get paltform device's domain instead of
>           reusing the PCI one in previous version
>         - Add a patch to rework iort_node_get_id()
> 
> [1]: http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1251993.html
> 
> v1 -> v2:
>         - Fix the bug of if multi Interrupt() resoures in single _PRS,
>           we need to calculate all the irq numbers (I missed it in previous
>           version);
>         - Rebased on Marc's irq/irqchip-4.9 branch and Lorenzo's v5
>           SMMU patches (also Robin's SMMu patches)
>         - Add patch irqchip: mbigen: promote mbigen init.
> 
> With platform msi support landed in the kernel, and the introduction
> of IORT for GICv3 ITS (PCI MSI) and SMMU, the framework for platform msi
> is ready, this patch set add few patches to enable the ACPI platform
> msi support.
> 
> For platform device connecting to ITS on arm platform, we have IORT
> table with the named componant node to describe the mappings of paltform
> device and ITS, so we can retrieve the dev id and find its parent
> irqdomain (ITS) from IORT table (simlar with the ACPI ITS support).
> 
> The fisrt 3 patches are cleanups;
> 
> Patch 4,5 are refactoring its_pmsi_prepare() for both DT and ACPI
> then retrieve the dev id from iort;
> 
> Patch 6,7 to create platform msi domain to ACPI case which scanned
> the MADT table;
> 
> Patch 8,9,10,11 to setup the msi domain for platform device based
> on IORT table.
> 
> Patch 12,13,14 convert dt based mbigen driver to support ACPI.
> 
> Teasted on Hisilicon D03/D05.
> 
> Happy holidays!
> 
> Thanks
> Hanjun
> 
> Hanjun Guo (12):
>   ACPI: ARM64: IORT: minor cleanup for iort_match_node_callback()
>   irqchip: gic-v3-its: keep the head file include in alphabetic order
>   ACPI: ARM64: IORT: add missing comment for iort_dev_find_its_id()
>   irqchip: gicv3-its: platform-msi: refactor its_pmsi_prepare()
>   ACPI: platform-msi: retrieve dev id from IORT
>   irqchip: gicv3-its: platform-msi: refactor its_pmsi_init() to prepare
>     for ACPI
>   irqchip: gicv3-its: platform-msi: scan MADT to create platform msi
>     domain
>   ACPI: ARM64: IORT: rework iort_node_get_id()
>   ACPI: platform: setup MSI domain for ACPI based platform device
>   ACPI: ARM64: IORT: rework iort_node_get_id() for NC->SMMU->ITS case
>   msi: platform: make platform_msi_create_device_domain() ACPI aware
>   irqchip: mbigen: Add ACPI support
> 
> Kefeng Wang (2):
>   irqchip: mbigen: drop module owner
>   irqchip: mbigen: introduce mbigen_of_create_domain()
> 
>  drivers/acpi/acpi_platform.c                  |  11 ++
>  drivers/acpi/arm64/iort.c                     | 138 ++++++++++++++++++++------
>  drivers/base/platform-msi.c                   |   3 +-
>  drivers/base/platform.c                       |   3 +
>  drivers/irqchip/irq-gic-v3-its-platform-msi.c | 106 +++++++++++++++-----
>  drivers/irqchip/irq-gic-v3-its.c              |   3 +-
>  drivers/irqchip/irq-mbigen.c                  | 109 ++++++++++++++++----
>  include/linux/acpi_iort.h                     |  11 ++
>  include/linux/platform_device.h               |   3 +
>  9 files changed, 309 insertions(+), 78 deletions(-)
> 

^ permalink raw reply

* [GIT PULL] Allwinner conversion to generic pin properties
From: Maxime Ripard @ 2016-12-26  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd, Olof,

Like we discussed it last time, here is a pull request with the
convertion patches to the generic pin properties for 4.10.

Thanks,
Maxime

The following changes since commit 7ce7d89f48834cefece7804d38fc5d85382edf77:

  Linux 4.10-rc1 (2016-12-25 16:13:08 -0800)

are available in the git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git tags/sunxi-generic-pinconf-for-4.10

for you to fetch changes up to 1edcd36fcb48fe841bcc62eda36c105037d9583c:

  ARM: sunxi: Convert pinctrl nodes to generic bindings (2016-12-26 08:27:11 +0100)

----------------------------------------------------------------
Allwinner conversion to generic pin muxing properties

Here is a list of patches that converts the current DT to the generic pin
control and muxing properties, now that the pinctrl driver supports it.

----------------------------------------------------------------
Maxime Ripard (3):
      ARM: sunxi: Remove useless allwinner,drive property
      ARM: sunxi: Remove useless allwinner,pull property
      ARM: sunxi: Convert pinctrl nodes to generic bindings

 arch/arm/boot/dts/sun4i-a10-a1000.dts              |  12 +-
 arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts         |   2 +-
 arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts    |  14 +-
 arch/arm/boot/dts/sun4i-a10-cubieboard.dts         |  14 +-
 arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts   |  38 ++-
 arch/arm/boot/dts/sun4i-a10-gemei-g9.dts           |   6 +-
 arch/arm/boot/dts/sun4i-a10-hackberry.dts          |  12 +-
 arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts       |  16 +-
 arch/arm/boot/dts/sun4i-a10-inet1.dts              |  26 +-
 arch/arm/boot/dts/sun4i-a10-inet97fv2.dts          |  14 +-
 arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts       |  29 +--
 arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts         |  12 +-
 arch/arm/boot/dts/sun4i-a10-marsboard.dts          |  13 +-
 arch/arm/boot/dts/sun4i-a10-mini-xplus.dts         |   2 +-
 arch/arm/boot/dts/sun4i-a10-mk802.dts              |  18 +-
 arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts     |  27 +-
 arch/arm/boot/dts/sun4i-a10-pcduino.dts            |  19 +-
 arch/arm/boot/dts/sun4i-a10-pcduino2.dts           |   6 +-
 arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts   |  32 +--
 arch/arm/boot/dts/sun4i-a10.dtsi                   | 169 +++++--------
 arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts       |  18 +-
 arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts       |  29 +--
 arch/arm/boot/dts/sun5i-a10s-mk802.dts             |  19 +-
 arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts   |  36 ++-
 arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts      |  20 +-
 arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts           |  21 +-
 arch/arm/boot/dts/sun5i-a10s.dtsi                  |  43 ++--
 .../boot/dts/sun5i-a13-empire-electronix-d709.dts  |  23 +-
 arch/arm/boot/dts/sun5i-a13-hsg-h702.dts           |  22 +-
 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts    |  40 ++-
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts          |  36 ++-
 arch/arm/boot/dts/sun5i-a13-utoo-p66.dts           |  11 +-
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  24 +-
 arch/arm/boot/dts/sun5i-gr8-chip-pro.dts           |  12 +-
 arch/arm/boot/dts/sun5i-gr8-evb.dts                |  24 +-
 arch/arm/boot/dts/sun5i-gr8.dtsi                   | 122 ++++-----
 arch/arm/boot/dts/sun5i-r8-chip.dts                |  27 +-
 .../boot/dts/sun5i-reference-design-tablet.dtsi    |  33 +--
 arch/arm/boot/dts/sun5i.dtsi                       |  75 +++---
 arch/arm/boot/dts/sun6i-a31-app4-evb1.dts          |   6 +-
 arch/arm/boot/dts/sun6i-a31-colombus.dts           |  22 +-
 arch/arm/boot/dts/sun6i-a31-hummingbird.dts        |  23 +-
 arch/arm/boot/dts/sun6i-a31-i7.dts                 |  19 +-
 arch/arm/boot/dts/sun6i-a31-m9.dts                 |  19 +-
 arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts   |  19 +-
 arch/arm/boot/dts/sun6i-a31.dtsi                   |  98 +++-----
 arch/arm/boot/dts/sun6i-a31s-primo81.dts           |  20 +-
 arch/arm/boot/dts/sun6i-a31s-sina31s.dts           |  13 +-
 arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts   |  29 +--
 .../dts/sun6i-a31s-yones-toptech-bs1078-v2.dts     |   9 +-
 .../boot/dts/sun6i-reference-design-tablet.dtsi    |  14 +-
 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts   |  27 +-
 arch/arm/boot/dts/sun7i-a20-bananapi.dts           |  26 +-
 arch/arm/boot/dts/sun7i-a20-bananapro.dts          |  37 +--
 arch/arm/boot/dts/sun7i-a20-cubieboard2.dts        |  13 +-
 arch/arm/boot/dts/sun7i-a20-cubietruck.dts         |  38 +--
 arch/arm/boot/dts/sun7i-a20-hummingbird.dts        |  24 +-
 arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts          |  26 +-
 arch/arm/boot/dts/sun7i-a20-itead-ibox.dts         |   7 +-
 arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts          |  30 +--
 arch/arm/boot/dts/sun7i-a20-m3.dts                 |   6 +-
 arch/arm/boot/dts/sun7i-a20-mk808c.dts             |  12 +-
 arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts     |  32 +--
 arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts     |  27 +-
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    |   6 +-
 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts    |  33 +--
 arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts    |  28 +--
 arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts      |  45 ++--
 arch/arm/boot/dts/sun7i-a20-orangepi.dts           |  38 ++-
 arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts      |  25 +-
 arch/arm/boot/dts/sun7i-a20-pcduino3.dts           |  21 +-
 arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts     |  25 +-
 arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts   |  13 +-
 arch/arm/boot/dts/sun7i-a20.dtsi                   | 277 ++++++++-------------
 arch/arm/boot/dts/sun8i-a23-a33.dtsi               |  99 +++-----
 arch/arm/boot/dts/sun8i-a23-evb.dts                |   7 +-
 .../boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts   |   8 +-
 .../boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts   |   8 +-
 arch/arm/boot/dts/sun8i-a33-inet-d978-rev2.dts     |   9 +-
 arch/arm/boot/dts/sun8i-a33-olinuxino.dts          |  18 +-
 arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts     |  11 +-
 arch/arm/boot/dts/sun8i-a33.dtsi                   |   6 +-
 arch/arm/boot/dts/sun8i-a83t.dtsi                  |  21 +-
 arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts    |  18 +-
 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi             |  18 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts          |  26 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts       |  18 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts        |  18 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts    |   4 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts         |  18 +-
 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts       |  10 +-
 arch/arm/boot/dts/sun8i-h3.dtsi                    | 104 +++-----
 arch/arm/boot/dts/sun8i-q8-common.dtsi             |   9 +-
 arch/arm/boot/dts/sun8i-r16-parrot.dts             |  36 ++-
 .../boot/dts/sun8i-reference-design-tablet.dtsi    |  26 +-
 arch/arm/boot/dts/sun9i-a80-cubieboard4.dts        |  23 +-
 arch/arm/boot/dts/sun9i-a80-optimus.dts            |  41 ++-
 arch/arm/boot/dts/sun9i-a80.dtsi                   |  61 ++---
 arch/arm/boot/dts/sunxi-common-regulators.dtsi     |  24 +-
 99 files changed, 1081 insertions(+), 1783 deletions(-)

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161226/d0e3042f/attachment.sig>

^ permalink raw reply

* [PATCH] coresight: fix kernel panic caused by invalid CPU
From: Wang Nan @ 2016-12-26  6:31 UTC (permalink / raw)
  To: linux-arm-kernel

Commit d52c9750f150 ("coresight: reset 'enable_sink' flag when need be")
caused a kernel panic because of the using of an invalid value: after
'for_each_cpu(cpu, mask)', value of local variable 'cpu' become invalid,
causes following 'cpu_to_node' access invalid memory area.

This patch brings the deleted 'cpu = cpumask_first(mask)' back.

Panic log:

 $ perf record -e cs_etm// ls

 Unable to handle kernel paging request at virtual address fffe801804af4f10
 pgd = ffff8017ce031600
 [fffe801804af4f10] *pgd=0000000000000000, *pud=0000000000000000
 Internal error: Oops: 96000004 [#1] SMP
 Modules linked in:
 CPU: 33 PID: 1619 Comm: perf Not tainted 4.7.1+ #16
 Hardware name: Huawei Taishan 2280 /CH05TEVBA, BIOS 1.10 11/24/2016
 task: ffff8017cb0c8400 ti: ffff8017cb154000 task.ti: ffff8017cb154000
 PC is at tmc_alloc_etf_buffer+0x60/0xd4
 LR is at tmc_alloc_etf_buffer+0x44/0xd4
 pc : [<ffff000008633df8>] lr : [<ffff000008633ddc>] pstate: 60000145
 sp : ffff8017cb157b40
 x29: ffff8017cb157b40 x28: 0000000000000000
 ...skip...
 7a60: ffff000008c64dc8 0000000000000006 0000000000000253 ffffffffffffffff
 7a80: 0000000000000000 0000000000000000 ffff0000080872cc 0000000000000001
 [<ffff000008633df8>] tmc_alloc_etf_buffer+0x60/0xd4
 [<ffff000008632b9c>] etm_setup_aux+0x1dc/0x1e8
 [<ffff00000816eed4>] rb_alloc_aux+0x2b0/0x338
 [<ffff00000816a5e4>] perf_mmap+0x414/0x568
 [<ffff0000081ab694>] mmap_region+0x324/0x544
 [<ffff0000081abbe8>] do_mmap+0x334/0x3e0
 [<ffff000008191150>] vm_mmap_pgoff+0xa4/0xc8
 [<ffff0000081a9a30>] SyS_mmap_pgoff+0xb0/0x22c
 [<ffff0000080872e4>] sys_mmap+0x18/0x28
 [<ffff0000080843f0>] el0_svc_naked+0x24/0x28
 Code: 912040a5 d0001c00 f873d821 911c6000 (b8656822)
 ---[ end trace 98933da8f92b0c9a ]---

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Xia Kaixu <xiakaixu@huawei.com>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
---
 drivers/hwtracing/coresight/coresight-etm-perf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 1774196..26cfac3 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -242,6 +242,7 @@ static void *etm_setup_aux(int event_cpu, void **pages,
 	if (!sink_ops(sink)->alloc_buffer)
 		goto err;
 
+	cpu = cpumask_first(mask);
 	/* Get the AUX specific data from the sink buffer */
 	event_data->snk_config =
 			sink_ops(sink)->alloc_buffer(sink, cpu, pages,
-- 
2.10.1

^ permalink raw reply related

* [PATCH 8/9] pinctrl: samsung: Add runtime PM support
From: Tomasz Figa @ 2016-12-26  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482495889-6201-9-git-send-email-m.szyprowski@samsung.com>

Hi,

2016-12-23 21:24 GMT+09:00 Marek Szyprowski <m.szyprowski@samsung.com>:
> This patch adds runtime power management support to Samsung pin controller
> driver. It uses recently introduced property to mark some pin states as
> suitable for power off. When all pins for given controller are set to this
> special state, the controller is able to enter runtime suspend state. This
> in turn might allow to turn respective power domain off to reduce power
> consumption.
>
> This patch moves saving driver state to runtime pm callbacks and implements
> system sleep suspend/resume callbacks with pm_runtime_force_suspend/resume
> helpers to keep the runtime pm state consistent with the hardware both
> during runtime and system sleep transitions.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/pinctrl/samsung/pinctrl-samsung.c | 24 ++++++++++++++++++++++--
>  drivers/pinctrl/samsung/pinctrl-samsung.h |  1 +
>  2 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> index 301169d2b6e1..c741e93d65b8 100644
> --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> @@ -28,6 +28,7 @@
>  #include <linux/gpio.h>
>  #include <linux/irqdomain.h>
>  #include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/spinlock.h>
>
>  #include "../core.h"
> @@ -378,6 +379,17 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
>                 shift -= 32;
>                 reg += 4;
>         }

nit: IMHO a blank line here would look better.

> +       if (func->rpm_active) {
> +               if (!(bank->rpm_map & (1 << pin_offset))) {

I think rpm_map could benefit from generic bitmap helpers.

> +                       bank->rpm_map |= 1 << pin_offset;
> +                       pm_runtime_get_sync(drvdata->dev);
> +               }
> +       } else {
> +               if ((bank->rpm_map & (1 << pin_offset))) {
> +                       bank->rpm_map &= ~(1 << pin_offset);
> +                       pm_runtime_put(drvdata->dev);
> +               }
> +       }

Then, the above could be simplified into:

        if (func->rpm_active && !test_bit(pin_offset, &bank->rpm_map)) {
                __set_bit(pin_offset, &bank->rpm_map);
                pm_runtime_get_sync(drvdata->dev);
        } else if (!func->rpm_active && test_bit(pin_offset, &bank->rpm_map) {
                __clear_bit(pin_offset, &bank->rpm_map);
                pm_runtime_put(drvdata->dev);
        }

>
>         spin_lock_irqsave(&bank->slock, flags);
>
> @@ -427,6 +439,8 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
>         if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
>                 return -EINVAL;
>
> +       pm_runtime_get_sync(drvdata->dev);
> +
>         width = type->fld_width[cfg_type];
>         cfg_reg = type->reg_offset[cfg_type];
>
> @@ -449,6 +463,8 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
>
>         spin_unlock_irqrestore(&bank->slock, flags);
>
> +       pm_runtime_put(drvdata->dev);
> +
>         return 0;
>  }
>
> @@ -1096,6 +1112,8 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
>                 ctrl->retention_init(drvdata);
>
>         platform_set_drvdata(pdev, drvdata);
> +       pm_runtime_set_active(dev);
> +       pm_runtime_enable(dev);

Can we really enable this unconditionally on all platforms?

>
>         return 0;
>  }
> @@ -1242,8 +1260,10 @@ static int samsung_pinctrl_resume(struct device *dev)
>  MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
>
>  static const struct dev_pm_ops samsung_pinctrl_pm_ops = {
> -       SET_LATE_SYSTEM_SLEEP_PM_OPS(samsung_pinctrl_suspend,
> -                                    samsung_pinctrl_resume)
> +       SET_RUNTIME_PM_OPS(samsung_pinctrl_suspend,
> +                          samsung_pinctrl_resume, NULL)
> +       SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> +                                    pm_runtime_force_resume)
>  };
>
>  static struct platform_driver samsung_pinctrl_driver = {
> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
> index edeafa00abd3..ccb24ec46796 100644
> --- a/drivers/pinctrl/samsung/pinctrl-samsung.h
> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
> @@ -172,6 +172,7 @@ struct samsung_pin_bank {
>         const char      *name;
>
>         u32             pin_base;
> +       u32             rpm_map;

This could be an unsigned long instead and then could benefit from the
bitmap helpers.

Best regards,
Tomasz

^ permalink raw reply

* [PATCH 7/9] pinctrl: samsung: Add property to mark pad state as suitable for power down
From: Tomasz Figa @ 2016-12-26  6:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161225191914.5bzl6fso36ozuum6@kozik-lap>

2016-12-26 4:19 GMT+09:00 Krzysztof Kozlowski <krzk@kernel.org>:
> On Fri, Dec 23, 2016 at 01:24:47PM +0100, Marek Szyprowski wrote:
>> Add support for special property "samsung,off-state", which indicates a special
>> state suitable for device's "sleep" state. Its pin values/properties should
>> match the configuration in power down mode. It indicates that pin controller
>> can notify runtime power management subsystem, that it is ready for runtime
>> suspend if its all pins are configured for such state. This in turn might
>> allow to turn respective power domain off to reduce power consumption.
>>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>>  Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt | 8 ++++++++
>>  drivers/pinctrl/samsung/pinctrl-samsung.c                     | 4 ++++
>>  drivers/pinctrl/samsung/pinctrl-samsung.h                     | 1 +
>>  3 files changed, 13 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>> index b7bd2e12a269..354eea0e7798 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
>> @@ -105,6 +105,7 @@ Required Properties:
>>    - samsung,pin-drv: Drive strength configuration.
>>    - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
>>    - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
>> +  - samsung,off-state: Mark this configuration as suitable for bank power off.
>>
>>    The values specified by these config properties should be derived from the
>>    hardware manual and these values are programmed as-is into the pin
>> @@ -113,6 +114,13 @@ Required Properties:
>>    Note: A child should include atleast a pin function selection property or
>>    pin configuration property (one or more) or both.
>>
>> +  Note: Special property "samsung,off-state" indicates that this state can
>> +  be used for device's "sleep" pins state. Its pin values/properties should
>> +  match the configuration in power down mode.
>
> Why power down values cannot be used for sleep state? Why you need
> separate pin control state? If pins values should match power down
> configuration, then they could just be added to default state, couldn't
> they?
>
> In the patch 2/9, existing configuration:
> 716         i2s0_bus: i2s0-bus {
> (...)
> 719                 samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
> 720                 samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
> 721                 samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
> 722         };
>
> additional configuration:
> +       i2s0_bus_slp: i2s0-bus-slp {
> +               samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
> +               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
> +               samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
> +               samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
> +               samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
> +               samsung,off-state;
> +       };

+1

If I'm not missing something, it should be reasonably easy to
determine if a state is suitable for power off by its configuration,
by comparing pin-function and pin-pud with pin-con-pdn and
pin-pud-pdn.

Best regards,
Tomasz

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox