* Re: [PATCHv2 10/10] Documentation: synopsys-dw-mshc: remove the unused properties
From: Shawn Lin @ 2016-11-16 9:21 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc, shawn.lin, devicetree, ulf.hansson, heiko, robh+dt
In-Reply-To: <20161115101232.3854-11-jh80.chung@samsung.com>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> "support-highspeed" was the obsoleted property.
> And "broken-cd" is not synopsys specific property.
> It can be referred to mmc.txt binding Documentation.
>
Ahh, I forgot to remove broken-cd from doc of dwmmc
when removing it from code.
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> index 1279a22..7fd17c3 100644
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -75,11 +75,6 @@ Optional properties:
> * card-detect-delay: Delay in milli-seconds before detecting card after card
> insert event. The default value is 0.
>
> -* supports-highspeed (DEPRECATED): Enables support for high speed cards (up to 50MHz)
> - (use "cap-mmc-highspeed" or "cap-sd-highspeed" instead)
> -
> -* broken-cd: as documented in mmc core bindings.
> -
> * vmmc-supply: The phandle to the regulator to use for vmmc. If this is
> specified we'll defer probe until we can find this regulator.
>
>
--
Best Regards
Shawn Lin
^ permalink raw reply
* Re: [PATCHv2 09/10] mmc: dw_mmc: The "clock-freq-min-max" property was deprecated
From: Shawn Lin @ 2016-11-16 9:19 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-10-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> The "clock-freq-min-max" property was deprecated.
> There is "max-frequency" property in drivers/mmc/core/host.c
> "max-frequency" can be replaced with "clock-freq-min-max".
> Minimum clock value might be set to 100K by default.
> Then MMC core should try to find the correct value from 400K to 100K.
> So it just needs to set Maximum clock value.
>
This is what we talked about to do :-)
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 3 ++-
> drivers/mmc/host/dw_mmc.c | 2 ++
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> index bfa461a..1279a22 100644
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -59,8 +59,9 @@ Optional properties:
> is specified and the ciu clock is specified then we'll try to set the ciu
> clock to this at probe time.
>
> -* clock-freq-min-max: Minimum and Maximum clock frequency for card output
> +* clock-freq-min-max (DEPRECATED): Minimum and Maximum clock frequency for card output
> clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
> + (Use the "max-frequency" instead of "clock-freq-min-max".)
>
> * num-slots: specifies the number of slots supported by the controller.
> The number of physical slots actually used could be equal or less than the
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index ec0ba79..48e968a 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -2608,6 +2608,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
> mmc->f_min = DW_MCI_FREQ_MIN;
> mmc->f_max = DW_MCI_FREQ_MAX;
> } else {
> + dev_info(host->dev,
> + "'clock-freq-min-max' property was deprecated.\n");
> mmc->f_min = freq[0];
> mmc->f_max = freq[1];
> }
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 08/10] mmc: dw_mmc: remove the unnecessary mmc_data structure
From: Shawn Lin @ 2016-11-16 9:18 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-9-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> Remove the unnecessary mmc_data structure.
> Instead, cmd->data can be used.
>
Looks good to me,
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index e912de6..ec0ba79 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -236,7 +236,6 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg);
>
> static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> {
> - struct mmc_data *data;
> struct dw_mci_slot *slot = mmc_priv(mmc);
> struct dw_mci *host = slot->host;
> u32 cmdr;
> @@ -291,10 +290,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> if (cmd->flags & MMC_RSP_CRC)
> cmdr |= SDMMC_CMD_RESP_CRC;
>
> - data = cmd->data;
> - if (data) {
> + if (cmd->data) {
> cmdr |= SDMMC_CMD_DAT_EXP;
> - if (data->flags & MMC_DATA_WRITE)
> + if (cmd->data->flags & MMC_DATA_WRITE)
> cmdr |= SDMMC_CMD_DAT_WR;
> }
>
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] ARM: dts: da850: add the mstpri and ddrctl nodes
From: Sekhar Nori @ 2016-11-16 9:17 UTC (permalink / raw)
To: Bartosz Golaszewski, Kevin Hilman, Michael Turquette, Rob Herring,
Frank Rowand, Mark Rutland, Peter Ujfalusi, Russell King
Cc: LKML, arm-soc, linux-drm, linux-devicetree, Jyri Sarha,
Tomi Valkeinen, David Airlie, Laurent Pinchart
In-Reply-To: <1479207611-18028-1-git-send-email-bgolaszewski@baylibre.com>
On Tuesday 15 November 2016 04:30 PM, Bartosz Golaszewski wrote:
> Add the nodes for the MSTPRI configuration and DDR2/mDDR memory
> controller drivers to da850.dtsi.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Applied to v4.10/dt
Thanks,
Sekhar
^ permalink raw reply
* Re: [PATCHv2 05/10] mmc: dw_mmc: call the dw_mci_prep_stop_abort() by default
From: Shawn Lin @ 2016-11-16 9:16 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-6-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> stop_cmdr should be set to values relevant to stop command.
> It migth be assigned to values whatever there is mrq->stop or not.
> Then it doesn't need to use dw_mci_prepare_command().
> It's enough to use the prep_stop_abort for preparing stop command.
>
Have you considered to clean up the logic of preparing abort cmd
within dw_mci_prepare_command?
if (cmd->opcode == MMC_STOP_TRANSMISSION ||
cmd->opcode == MMC_GO_IDLE_STATE ||
cmd->opcode == MMC_GO_INACTIVE_STATE ||
(cmd->opcode == SD_IO_RW_DIRECT &&
((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT))
cmdr |= SDMMC_CMD_STOP;
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 15 +++++----------
> 1 file changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 3cda68c..12e1107 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -385,7 +385,7 @@ static void dw_mci_start_command(struct dw_mci *host,
>
> static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
> {
> - struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
> + struct mmc_command *stop = &host->stop_abort;
>
> dw_mci_start_command(host, stop, host->stop_cmdr);
> }
> @@ -1277,10 +1277,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
> spin_unlock_irqrestore(&host->irq_lock, irqflags);
> }
>
> - if (mrq->stop)
> - host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
> - else
> - host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
> + host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
> }
>
> static void dw_mci_start_request(struct dw_mci *host,
> @@ -1890,8 +1887,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> if (test_and_clear_bit(EVENT_DATA_ERROR,
> &host->pending_events)) {
> dw_mci_stop_dma(host);
> - if (data->stop ||
> - !(host->data_status & (SDMMC_INT_DRTO |
> + if (!(host->data_status & (SDMMC_INT_DRTO |
> SDMMC_INT_EBE)))
> send_stop_abort(host, data);
> state = STATE_DATA_ERROR;
> @@ -1927,8 +1923,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> if (test_and_clear_bit(EVENT_DATA_ERROR,
> &host->pending_events)) {
> dw_mci_stop_dma(host);
> - if (data->stop ||
> - !(host->data_status & (SDMMC_INT_DRTO |
> + if (!(host->data_status & (SDMMC_INT_DRTO |
> SDMMC_INT_EBE)))
> send_stop_abort(host, data);
> state = STATE_DATA_ERROR;
> @@ -2004,7 +1999,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> host->cmd = NULL;
> host->data = NULL;
>
> - if (mrq->stop)
> + if (!mrq->sbc && mrq->stop)
> dw_mci_command_complete(host, mrq->stop);
> else
> host->cmd_status = 0;
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 04/10] mmc: dw_mmc: use the hold register when send stop command
From: Shawn Lin @ 2016-11-16 9:09 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-5-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> If DW_MMC_CARD_NO_USE_HOLD isn't set, it's usesd by default.
> Enve if SDMMC_CMD_USB_HOLD_REG is set in prepare_command(), but it
> doesn't set in pre_stop_abort().
>
> To maintain the consistency, add the checking condition for this.
Actually I hacked the driver w/ or w/o this patch to see how the
controller would do when looking at your V1.
Interesting, I didn't see failure when missing to set this...But
definitely it should be fixed.
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index be36f48..3cda68c 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -337,6 +337,9 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
> cmdr = stop->opcode | SDMMC_CMD_STOP |
> SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
>
> + if (!test_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags))
> + cmdr |= SDMMC_CMD_USE_HOLD_REG;
> +
> return cmdr;
> }
>
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCHv0 1/1] fbdev: add Intel FPGA FRAME BUFFER driver
From: Ong, Hean Loong @ 2016-11-16 9:07 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: devicetree, linux-kernel, linux-fbdev, Ong Hean Loong
From: Ong Hean Loong <hean.loong.ong@intel.com>
This patch enables the display port IP driver for
Intel Arria 10 SOCFPGA Golden Hardware
Reference Design (GHRD).
The driver requires enabling the options such as
Coheherent Memory Allocation,
Intel FPGA Frame Buffer, Frame Buffer Conasole
Signed-off-by: Ong Hean Loong <hean.loong.ong@intel.com>
---
.../devicetree/bindings/video/intelfpgavipfb.txt | 22 ++
MAINTAINERS | 6 +
drivers/video/fbdev/Kconfig | 15 +
drivers/video/fbdev/Makefile | 1 +
drivers/video/fbdev/intelfpgavipfb.c | 302 ++++++++++++++++++++
5 files changed, 346 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/intelfpgavipfb.txt
create mode 100644 drivers/video/fbdev/intelfpgavipfb.c
diff --git a/Documentation/devicetree/bindings/video/intelfpgavipfb.txt b/Documentation/devicetree/bindings/video/intelfpgavipfb.txt
new file mode 100644
index 0000000..8928c99
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/intelfpgavipfb.txt
@@ -0,0 +1,22 @@
+Intel FPGA Video and Image Processing(VIP) Frame Buffer bindings
+
+Required properties:
+- compatible: "intel,vip-frame-buffer2"
+- reg: Physical base address and length of the framebuffer controller's
+ registers.
+- max-width: The width of the framebuffer in pixels.
+- max-height: The height of the framebuffer in pixels.
+- bits-per-color: only "8" is currently supported
+- mem-word-width = the bus width of the avalon master port on the frame reader
+
+Example:
+
+alt_vip_vfr_0: vip@0xff260000 {
+ compatible = "intel,vip-frame-buffer2";
+ reg = <0xff260000 0x00000080>;
+ max-width = <1024>;
+ max-height = <768>;
+ bits-per-color = <8>;
+ mem-word-width = <128>;
+};
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 4012c2f..bfc2687 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6314,6 +6314,12 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/i810/
+INTEL FPGA FRAMEBUFFER DRIVER
+M: Ong, Hean Loong <hean.loong.ong@intel.com>
+L: linux-fbdev@vger.kernel.org
+S: Maintained
+F: drivers/video/fbdev/intvipfb.c
+
INTEL MENLOW THERMAL DRIVER
M: Sujith Thomas <sujith.thomas@intel.com>
L: platform-driver-x86@vger.kernel.org
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 5d3b0db..5c9d674 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -228,6 +228,21 @@ config FB_TILEBLITTING
comment "Frame buffer hardware drivers"
depends on FB
+config FB_INTEL_FPGA_VIP
+ tristate "Intel FPGA VIP framebuffer support"
+ depends on FB
+ select CMA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FRAMEBUFFER_CONSOLE
+ select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
+ ---help---
+ The FB_INTEL_FPGA_VIP driver supports the formerly Altera Video and Image Processing(VIP)
+ Frame Buffer II. Requires CONFIG_CMA and Frame Buffer Console to
+ be enabled as well. The driver currently only supports ARRIA 10 board from the Intel
+ FPGA Reference Design board family.
+
config FB_GRVGA
tristate "Aeroflex Gaisler framebuffer support"
depends on FB && SPARC
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index ee8c814..6c30549 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
# Hardware specific drivers go first
+obj-$(CONFIG_FB_INTEL_FPGA_VIP) += intelfpgavipfb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o
diff --git a/drivers/video/fbdev/intelfpgavipfb.c b/drivers/video/fbdev/intelfpgavipfb.c
new file mode 100644
index 0000000..9f5ca26
--- /dev/null
+++ b/drivers/video/fbdev/intelfpgavipfb.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All rights reserved
+ *
+ * intelfpgavipfb.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This is based on a driver made by Thomas Chou <thomas@wytron.com.tw> and
+ * Winteler Goossens <wintelergoossens@home.nl> This driver supports the
+ * Intel VIP Frame Buffer II component. More info on the hardware can be
+ * found in the Intel Video and Image Processing Suite User Guide at
+ * http://www.intelera.com/literature/ug/ug_vip.pdf.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define PALETTE_SIZE 256
+#define DRIVER_NAME "intelvipfb"
+
+/* control registers */
+#define INTVIPFB2_CONTROL 0
+#define INTVIPFB2_STATUS 0x4
+#define INTVIPFB2_INTERRUPT 0x8
+#define INTVIPFB2_FRAME_COUNTER 0xC
+#define INTVIPFB2_FRAME_DROP 0x10
+#define INTVIPFB2_FRAME_INFO 0x14
+#define INTVIPFB2_FRAME_START 0x18
+#define INTVIPFB2_FRAME_READER 0x1C
+
+#define BITS_PER_PIXEL 32
+
+struct intelvipfb_dev {
+ struct platform_device *pdev;
+ struct fb_info info;
+ struct resource *reg_res;
+ void __iomem *base;
+ int mem_word_width;
+ u32 pseudo_palette[PALETTE_SIZE];
+};
+
+static int intelvipfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
+{
+ /*
+ * Set a single color register. The values supplied have a 32 bit
+ * magnitude.
+ * Return != 0 for invalid regno.
+ */
+
+ if (regno > 255)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ if (regno < 255) {
+ ((u32 *)info->pseudo_palette)[regno] =
+ ((red & 255) << 16) | ((green & 255) << 8) | (blue & 255);
+ }
+
+ return 0;
+}
+
+static struct fb_ops intelvipfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_setcolreg = intelvipfb_setcolreg,
+};
+
+static int intelvipfb_of_setup(struct intelvipfb_dev *fbdev)
+{
+ struct device_node *np = fbdev->pdev->dev.of_node;
+ int ret;
+ u32 bits_per_color;
+
+ ret = of_property_read_u32(np, "max-width", &fbdev->info.var.xres);
+ if (ret) {
+ dev_err(&fbdev->pdev->dev,
+ "Missing required parameter 'max-width'");
+ return ret;
+ }
+ fbdev->info.var.xres_virtual = fbdev->info.var.xres,
+
+ ret = of_property_read_u32(np, "max-height", &fbdev->info.var.yres);
+ if (ret) {
+ dev_err(&fbdev->pdev->dev,
+ "Missing required parameter 'max-height'");
+ return ret;
+ }
+ fbdev->info.var.yres_virtual = fbdev->info.var.yres;
+
+ ret = of_property_read_u32(np, "bits-per-color", &bits_per_color);
+ if (ret) {
+ dev_err(&fbdev->pdev->dev,
+ "Missing required parameter 'bits-per-color'");
+ return ret;
+ }
+ if (bits_per_color != 8) {
+ dev_err(&fbdev->pdev->dev,
+ "bits-per-color is set to %i. Currently only 8 is supported.",
+ bits_per_color);
+ return -ENODEV;
+ }
+ fbdev->info.var.bits_per_pixel = BITS_PER_PIXEL;
+
+ ret = of_property_read_u32(np, "mem-word-width",
+ &fbdev->mem_word_width);
+ if (ret) {
+ dev_err(&fbdev->pdev->dev,
+ "Missing required parameter 'mem-word-width'");
+ return ret;
+ }
+ if (!(fbdev->mem_word_width >= BITS_PER_PIXEL &&
+ fbdev->mem_word_width % BITS_PER_PIXEL == 0)) {
+ dev_err(&fbdev->pdev->dev,
+ "mem-word-width is set to %i. must be >= 32 and multiple of 32.",
+ fbdev->mem_word_width);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void intelvipfb_start_hw(struct intelvipfb_dev *fbdev)
+{
+ /*
+ * The frameinfo variable has to correspond to the size of the VIP Suite
+ * Frame Reader register 7 which will determine the maximum size used
+ * in this frameinfo
+ */
+ u32 frameinfo = readl(fbdev->base +
+ INTVIPFB2_FRAME_READER) & 0x00ffffff;
+
+ writel(frameinfo, fbdev->base + INTVIPFB2_FRAME_INFO);
+ writel(fbdev->info.fix.smem_start, fbdev->base + INTVIPFB2_FRAME_START);
+ /* Finally set the control register to 1 to start streaming */
+ writel(1, fbdev->base + INTVIPFB2_CONTROL);
+}
+
+static void intelvipfb_disable_hw(struct intelvipfb_dev *fbdev)
+{
+ /* set the control register to 0 to stop streaming */
+ writel(0, fbdev->base + INTVIPFB2_CONTROL);
+}
+
+static int intelvipfb_setup_fb_info(struct intelvipfb_dev *fbdev)
+{
+ struct fb_info *info = &fbdev->info;
+ int ret;
+
+ strcpy(info->fix.id, DRIVER_NAME);
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->fbops = &intelvipfb_ops;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ ret = intelvipfb_of_setup(fbdev);
+ if (ret)
+ return ret;
+
+ /* settings for 32bit pixels */
+ info->var.red.offset = 16;
+ info->var.red.length = 8;
+ info->var.red.msb_right = 0;
+ info->var.green.offset = 8;
+ info->var.green.length = 8;
+ info->var.green.msb_right = 0;
+ info->var.blue.offset = 0;
+ info->var.blue.length = 8;
+ info->var.blue.msb_right = 0;
+
+ info->fix.line_length = (info->var.xres *
+ (info->var.bits_per_pixel >> 3));
+ info->fix.smem_len = info->fix.line_length * info->var.yres;
+
+ info->pseudo_palette = fbdev->pseudo_palette;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ return 0;
+}
+
+static int intelvipfb_probe(struct platform_device *pdev)
+{
+ int retval;
+ void *fbmem_virt;
+ struct intelvipfb_dev *fbdev;
+
+ fbdev = devm_kzalloc(&pdev->dev, sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev)
+ return -ENOMEM;
+
+ fbdev->pdev = pdev;
+ fbdev->reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!fbdev->reg_res)
+ return -ENODEV;
+
+ fbdev->base = devm_ioremap_resource(&pdev->dev, fbdev->reg_res);
+ if (IS_ERR(fbdev->base)) {
+ dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+ retval = PTR_ERR(fbdev->base);
+ return -ENODEV;
+ }
+
+ retval = intelvipfb_setup_fb_info(fbdev);
+
+ fbmem_virt = dma_alloc_coherent(NULL,
+ fbdev->info.fix.smem_len,
+ (void *)&fbdev->info.fix.smem_start,
+ GFP_KERNEL);
+ if (!fbmem_virt) {
+ dev_err(&pdev->dev,
+ "intelvipfb: unable to allocate %d Bytes fb memory\n",
+ fbdev->info.fix.smem_len);
+ return retval;
+ }
+
+ fbdev->info.screen_base = fbmem_virt;
+
+ retval = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0);
+ if (retval < 0)
+ goto err_dma_free;
+
+ platform_set_drvdata(pdev, fbdev);
+
+ intelvipfb_start_hw(fbdev);
+
+ retval = register_framebuffer(&fbdev->info);
+ if (retval < 0)
+ goto err_dealloc_cmap;
+
+ dev_info(&pdev->dev, "fb%d: %s frame buffer device at 0x%x+0x%x\n",
+ fbdev->info.node, fbdev->info.fix.id,
+ (unsigned int)fbdev->info.fix.smem_start,
+ fbdev->info.fix.smem_len);
+
+ return 0;
+
+err_dealloc_cmap:
+ fb_dealloc_cmap(&fbdev->info.cmap);
+err_dma_free:
+ dma_free_coherent(NULL, fbdev->info.fix.smem_len, fbmem_virt,
+ fbdev->info.fix.smem_start);
+ return retval;
+}
+
+static int intelvipfb_remove(struct platform_device *dev)
+{
+ struct intelvipfb_dev *fbdev = platform_get_drvdata(dev);
+
+ if (fbdev) {
+ unregister_framebuffer(&fbdev->info);
+ fb_dealloc_cmap(&fbdev->info.cmap);
+ dma_free_coherent(NULL, fbdev->info.fix.smem_len,
+ fbdev->info.screen_base,
+ fbdev->info.fix.smem_start);
+ intelvipfb_disable_hw(fbdev);
+ }
+ return 0;
+}
+
+static const struct of_device_id intelvipfb_match[] = {
+ { .compatible = "intel,vip-frame-buffer2" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, intelvipfb_match);
+
+static struct platform_driver intelvipfb_driver = {
+ .probe = intelvipfb_probe,
+ .remove = intelvipfb_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = intelvipfb_match,
+ },
+};
+module_platform_driver(intelvipfb_driver);
+
+MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
+MODULE_AUTHOR("Chris Rauer <christopher.rauer@intel.com>");
+MODULE_LICENSE("GPL v2");
+
--
1.7.1
^ permalink raw reply related
* Re: [PATCHv2 03/10] mmc: dw_mmc: change the DW_MCI_FREQ_MIN from 400K to 100K
From: Shawn Lin @ 2016-11-16 9:06 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-4-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> If there is no property "clock-freq-min-max", mmc->f_min should be set
> to 400K by default. But Some SoC can be used 100K.
> When 100K is used, MMC core will try to check from 400K to 100K.
>
> Reported-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
It makes more sense that the original 400KHz, thanks for improving
that.
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 6c0c4c5..be36f48 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -54,7 +54,7 @@
> #define DW_MCI_DMA_THRESHOLD 16
>
> #define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */
> -#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */
> +#define DW_MCI_FREQ_MIN 100000 /* unit: HZ */
>
> #define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
> SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 01/10] mmc: dw_mmc: display the real register value on debugfs
From: Shawn Lin @ 2016-11-16 9:04 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-2-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
在 2016/11/15 18:12, Jaehoon Chung 写道:
> Developer wants to see the real register value, not register offset.
> This patch fixed to display the real value of register.
>
IIRC, you had submited some similar patch but I don't remember
why it wasn't merged?
Anyway,
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a16c537..e53899e 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -165,12 +165,14 @@ static const struct file_operations dw_mci_req_fops = {
>
> static int dw_mci_regs_show(struct seq_file *s, void *v)
> {
> - seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
> - seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
> - seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
> - seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
> - seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
> - seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
> + struct dw_mci *host = s->private;
> +
> + seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
> + seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
> + seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
> + seq_printf(s, "CTRL:\t0x%08x\n", mci_readl(host, CTRL));
> + seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
> + seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
>
> return 0;
> }
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16 9:04 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc
Cc: devicetree, Ulf Hansson, heiko, shawn.lin, robh+dt
In-Reply-To: <4168313a-07bc-00a7-ecc8-1ca4978c4d8c@samsung.com>
On 16/11/16 10:58, Jaehoon Chung wrote:
> On 11/16/2016 05:28 PM, Adrian Hunter wrote:
>> On 16/11/16 10:25, Jaehoon Chung wrote:
>>> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>>>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>>>> Added Adrian for sdhci.h
>>>>>
>>>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>>>> It's not for only sdhci controller.
>>>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>>>> to mmc_cookie.
>>>>
>>>> The cookie is currently host private data, so I don't understand the
>>>> motivation behind this.
>>>
>>> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
>>>
>>> So i think it can be used about both sdhci and dwmmc.
>>> Is there no reason that add the private dwmmc data?
>>>
>>> With these cookie value, update the dwmmc controller for post/pre_req().
>>>
>>> https://patchwork.kernel.org/patch/9429287/
>>
>> So why not define dwmmc cookies in dw_mmc.c ?
>
> Because I understood that it's not sdhci specific cookies. It can be used generally, doesn't?
>
> Role of post/pre_req() in host controller is the doing dma_map/unmap().
> And data's cookies only needs to notice whether dma is mapped or unmapped, etc.
>
> Well, If it's really private value and should be added other cookies values in future, i will put cookies in dw_mmc.h.
> (it should be duplicated in sdhci and dwmmc.)
Probably all host controllers should do cookies the same way, but they don't
at the moment, so there is no reason to share definitions.
^ permalink raw reply
* Re: [PATCHv2 02/10] mmc: dw_mmc: fix the debug message for checking card's present
From: Shawn Lin @ 2016-11-16 9:01 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
shawn.lin-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, heiko-4mtYJXux2i+zQB+pC5nmwQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161115101232.3854-3-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
On 2016/11/15 18:12, Jaehoon Chung wrote:
> If display the debug message, this message should be spamming.
> If flags is maintained the previous value, didn't display the debug
> message.
>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
Looks correct to me,
Reviewed-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
> drivers/mmc/host/dw_mmc.c | 7 ++-----
> 1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index e53899e..6c0c4c5 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1537,13 +1537,10 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> == 0 ? 1 : 0;
>
> spin_lock_bh(&host->lock);
> - if (present) {
> - set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
> + if (present && !test_and_set_bit(DW_MMC_CARD_PRESENT, &slot->flags))
> dev_dbg(&mmc->class_dev, "card is present\n");
> - } else {
> - clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
> + else if (!test_and_clear_bit(DW_MMC_CARD_PRESENT, &slot->flags))
> dev_dbg(&mmc->class_dev, "card is not present\n");
> - }
> spin_unlock_bh(&host->lock);
>
> return present;
>
--
Best Regards
Shawn Lin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16 8:58 UTC (permalink / raw)
To: Adrian Hunter, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <d5321daf-b449-e556-ccf1-cd82d497ea85-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
On 11/16/2016 05:28 PM, Adrian Hunter wrote:
> On 16/11/16 10:25, Jaehoon Chung wrote:
>> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>>> Added Adrian for sdhci.h
>>>>
>>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>>> It's not for only sdhci controller.
>>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>>> to mmc_cookie.
>>>
>>> The cookie is currently host private data, so I don't understand the
>>> motivation behind this.
>>
>> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
>>
>> So i think it can be used about both sdhci and dwmmc.
>> Is there no reason that add the private dwmmc data?
>>
>> With these cookie value, update the dwmmc controller for post/pre_req().
>>
>> https://patchwork.kernel.org/patch/9429287/
>
> So why not define dwmmc cookies in dw_mmc.c ?
Because I understood that it's not sdhci specific cookies. It can be used generally, doesn't?
Role of post/pre_req() in host controller is the doing dma_map/unmap().
And data's cookies only needs to notice whether dma is mapped or unmapped, etc.
Well, If it's really private value and should be added other cookies values in future, i will put cookies in dw_mmc.h.
(it should be duplicated in sdhci and dwmmc.)
Best Regards,
Jaehoon Chung
>
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/3] arm: hisi: add ARCH_MULTI_V5 support
From: wenpan @ 2016-11-16 8:56 UTC (permalink / raw)
To: Arnd Bergmann, Marty Plummer
Cc: mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
howell.yang-C8/M+/jPZTeaMJb+Lgu22Q,
xuejiancheng-C8/M+/jPZTeaMJb+Lgu22Q,
jalen.hsu-C8/M+/jPZTeaMJb+Lgu22Q,
lvkuanliang-C8/M+/jPZTeaMJb+Lgu22Q,
suwenping-C8/M+/jPZTeaMJb+Lgu22Q, raojun-C8/M+/jPZTeaMJb+Lgu22Q,
kevin.lixu-C8/M+/jPZTeaMJb+Lgu22Q,
qinxiaojun-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <5893354.6MrIxqzRoI@wuerfel>
Hi Martyo<\f
Does this confict with your patcho<\x1f If noto<\fI hope this could be merged first. Besides could you tell me the link to your related patch?
Thanks,
Pan
On 2016/10/17 21:48, Arnd Bergmann wrote:
> On Monday, October 17, 2016 8:07:03 PM CEST Pan Wen wrote:
>> Add support for some HiSilicon SoCs which depend on ARCH_MULTI_V5.
>>
>> Signed-off-by: Pan Wen <wenpan-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>>
>
> Looks ok. I've added Marty Plummer to Cc, he was recently proposing
> patches for Hi3520, which I think is closely related to this one.
> Please try to work together so the patches don't conflict. It should
> be fairly straightforward since you are basically doing the same
> change here.
>
> Arnd
>
> .
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v7 08/14] mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
From: Ritesh Harjani @ 2016-11-16 8:53 UTC (permalink / raw)
To: Adrian Hunter, Stephen Boyd, ulf.hansson
Cc: linux-mmc, shawn.lin, andy.gross, devicetree, linux-clk,
david.brown, linux-arm-msm, georgi.djakov, alex.lemberg,
mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman, david.griego,
stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <875c9051-bd8b-60cf-82e4-3e26612a8623@intel.com>
On 11/16/2016 1:12 PM, Adrian Hunter wrote:
> On 16/11/16 06:42, Ritesh Harjani wrote:
>> Hi,
>>
>> On 11/15/2016 10:40 AM, Ritesh Harjani wrote:
>>> Hi Stephen/Adrian,
>>>
>>> On 11/15/2016 1:07 AM, Stephen Boyd wrote:
>>>> On 11/14, Ritesh Harjani wrote:
>>>>> @@ -577,6 +578,90 @@ static unsigned int
>>>>> sdhci_msm_get_min_clock(struct sdhci_host *host)
>>>>> return SDHCI_MSM_MIN_CLOCK;
>>>>> }
>>>>>
>>>>> +/**
>>>>> + * __sdhci_msm_set_clock - sdhci_msm clock control.
>>>>> + *
>>>>> + * Description:
>>>>> + * Implement MSM version of sdhci_set_clock.
>>>>> + * This is required since MSM controller does not
>>>>> + * use internal divider and instead directly control
>>>>> + * the GCC clock as per HW recommendation.
>>>>> + **/
>>>>> +void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>>>>> +{
>>>>> + u16 clk;
>>>>> + unsigned long timeout;
>>>>> +
>>>>> + /*
>>>>> + * Keep actual_clock as zero -
>>>>> + * - since there is no divider used so no need of having
>>>>> actual_clock.
>>>>> + * - MSM controller uses SDCLK for data timeout calculation. If
>>>>> + * actual_clock is zero, host->clock is taken for calculation.
>>>>> + */
>>>>> + host->mmc->actual_clock = 0;
>>>>> +
>>>>> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> + if (clock == 0)
>>>>> + return;
>>>>> +
>>>>> + /*
>>>>> + * MSM controller do not use clock divider.
>>>>> + * Thus read SDHCI_CLOCK_CONTROL and only enable
>>>>> + * clock with no divider value programmed.
>>>>> + */
>>>>> + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> + clk |= SDHCI_CLOCK_INT_EN;
>>>>> + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>>> +
>>>>> + /* Wait max 20 ms */
>>>>> + timeout = 20;
>>>>> + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>>>>> + & SDHCI_CLOCK_INT_STABLE)) {
>>>>> + if (timeout == 0) {
>>>>> + pr_err("%s: Internal clock never stabilised\n",
>>>>> + mmc_hostname(host->mmc));
>>>>> + return;
>>>>> + }
>>>>> + timeout--;
>>>>> + mdelay(1);
>>>>> + }
>>>>> +
>>>>> + clk |= SDHCI_CLOCK_CARD_EN;
>>>>> + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>>
>>>> This is almost a copy/paste of sdhci_set_clock(). Can we make
>>>> sdhci_set_clock() call a __sdhci_set_clock() function that takes
>>>> unsigned int clock, and also a flag indicating if we want to set
>>>> the internal clock divider or not? Then we can call
>>>> __sdhci_set_clock() from sdhci_set_clock() with (clock, true) as
>>>> arguments and (clock, false).
>> Actually what you may be referring here is some sort of quirks which is not
>> entertained any more for sdhci driver.
>> sdhci is tending towards becoming a library and hence such changes are
>> restricted.
>>
>> But I think we may do below changes to avoid duplication of code which
>> enables the sdhci internal clock and waits for internal clock to be stable.
>>
>> Adrian, could you please tell if this should be ok?
>
> That seems fine, but the name seems too long - how about changing
> sdhci_set_clock_enable to sdhci_enable_clk.
Sure. Will make the changes then.
>
>> Then we may be able to call for sdhci_set_clock_enable function from
>> sdhci_msm_set_clock.
>>
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 42ef3eb..28e605c 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1343,19 +1343,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned
>> int clock,
>> }
>> EXPORT_SYMBOL_GPL(sdhci_calc_clk);
>>
>> -void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
>> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk)
>> {
>> - u16 clk;
>> - unsigned long timeout;
>> -
>> - host->mmc->actual_clock = 0;
>> -
>> - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>> -
>> - if (clock == 0)
>> - return;
>> -
>> - clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
>>
>> clk |= SDHCI_CLOCK_INT_EN;
>> sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>> @@ -1377,6 +1366,24 @@ void sdhci_set_clock(struct sdhci_host *host,
>> unsigned int clock)
>> clk |= SDHCI_CLOCK_CARD_EN;
>> sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>> }
>> +EXPORT_SYMBOL_GPL(sdhci_set_clock_enable);
>> +
>> +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
>> +{
>> + u16 clk;
>> + unsigned long timeout;
>> +
>> + host->mmc->actual_clock = 0;
>> +
>> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>> +
>> + if (clock == 0)
>> + return;
>> +
>> + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
>> +
>> + sdhci_set_clock_enable(host, clk);
>> +}
>> EXPORT_SYMBOL_GPL(sdhci_set_clock);
>>
>> static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 766df17..43382e1 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -681,6 +681,7 @@ static inline bool sdhci_sdio_irq_enabled(struct
>> sdhci_host *host)
>> u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
>> unsigned int *actual_clock);
>> void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
>> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk);
>> void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>> unsigned short vdd);
>> void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
>>
>>
>>
>>> Adrian,
>>> Could you please comment here ?
>>>
>>>>
>>>>> +}
>>>>> +
>>>>> +/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
>>>>> +static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned
>>>>> int clock)
>>>>> +{
>>>>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>>> + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>>>>> + int rc;
>>>>> +
>>>>> + if (!clock) {
>>>>> + msm_host->clk_rate = clock;
>>>>> + goto out;
>>>>> + }
>>>>> +
>>>>> + spin_unlock_irq(&host->lock);
>>>>> + if (clock != msm_host->clk_rate) {
>>>>
>>>> Why do we need to check here? Can't we call clk_set_rate()
>>>> Unconditionally?
>>> Since it may so happen that above layers may call for ->set_clock
>>> function with same requested clock more than once, hence we cache the
>>> host->clock here.
>>> Also, since requested clock (host->clock) can be say 400Mhz but the
>>> actual pltfm supported clock would be say 384MHz.
>>>
>>>
>>>>
>>>>> + rc = clk_set_rate(msm_host->clk, clock);
>>>>> + if (rc) {
>>>>> + pr_err("%s: Failed to set clock at rate %u\n",
>>>>> + mmc_hostname(host->mmc), clock);
>>>>> + spin_lock_irq(&host->lock);
>>>>> + goto out;
>>>>
>>>> Or replace the above two lines with goto err;
>>> Ok, I will have another label out_lock instead of err.
>>>>
>>>>> + }
>>>>> + msm_host->clk_rate = clock;
>>>>> + pr_debug("%s: Setting clock at rate %lu\n",
>>>>> + mmc_hostname(host->mmc), clk_get_rate(msm_host->clk));
>>>>> + }
>>>>
>>>> And put an err label here.
>>> will put the label here as out_lock;
>>>>
>>>>> + spin_lock_irq(&host->lock);
>>>>> +out:
>>>>> + __sdhci_msm_set_clock(host, clock);
>>>>> +}
>>>>> +
>>>>> static const struct of_device_id sdhci_msm_dt_match[] = {
>>>>> { .compatible = "qcom,sdhci-msm-v4" },
>>>>> {},
>>>>
>>>
>>
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v3 3/3] clk: rockchip: add clock controller for rk1108
From: Shawn Lin @ 2016-11-16 8:49 UTC (permalink / raw)
To: Heiko Stuebner
Cc: Stephen Boyd, Rob Herring, devicetree, Andy Yan,
Michael Turquette, linux-clk, linux-rockchip, Shawn Lin
In-Reply-To: <1479286163-34789-1-git-send-email-shawn.lin@rock-chips.com>
Add the clock tree definition and driver for rk1108 SoC.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Tested-by: Jacob Chen <jacob2.chen@rock-chips.com>
---
Changes in v3:
- remove some unused clk parent and add some new parent
to complete all the input clocks.
Changes in v2:
- fix some CodingStyle issues
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-rk1108.c | 531 ++++++++++++++++++++++++++++++++++++++
drivers/clk/rockchip/clk.h | 15 ++
3 files changed, 547 insertions(+)
create mode 100644 drivers/clk/rockchip/clk-rk1108.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index b5f2c8e..16e098c 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o
obj-y += clk-ddr.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
+obj-y += clk-rk1108.o
obj-y += clk-rk3036.o
obj-y += clk-rk3188.o
obj-y += clk-rk3228.o
diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c
new file mode 100644
index 0000000..92750d7
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk1108.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ * Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include "clk.h"
+
+#define RK1108_GRF_SOC_STATUS0 0x480
+
+enum rk1108_plls {
+ apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+#define RK1108_DIV_CORE_MASK 0xf
+#define RK1108_DIV_CORE_SHIFT 4
+
+#define RK1108_CLKSEL0(_core_peri_div) \
+ { \
+ .reg = RK1108_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
+ RK1108_DIV_CORE_SHIFT) \
+ }
+
+#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \
+ { \
+ .prate = _prate, \
+ .divs = { \
+ RK1108_CLKSEL0(_core_peri_div), \
+ }, \
+ }
+
+static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
+ RK1108_CPUCLK_RATE(816000000, 4),
+ RK1108_CPUCLK_RATE(600000000, 4),
+ RK1108_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
+ .core_reg = RK1108_CLKSEL_CON(0),
+ .div_core_shift = 0,
+ .div_core_mask = 0x1f,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
+ .mux_core_shift = 8,
+ .mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin24m"};
+PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" };
+PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" };
+PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
+PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" };
+PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" };
+PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" };
+PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" };
+PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
+PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
+PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" };
+PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" };
+PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" };
+PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" };
+PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" };
+
+static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
+ RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
+ [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
+ RK1108_PLL_CON(11), 8, 31, 0, NULL),
+ [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
+ RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+ MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+ MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+ MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+ MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
+ RK1108_MISC_CON, 13, 2, MFLAGS),
+ MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
+ RK1108_MISC_CON, 15, 2, MFLAGS),
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ /* PD_CORE */
+ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 0, GFLAGS),
+ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK1108_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK1108_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(11), 0, GFLAGS),
+ GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(11), 1, GFLAGS),
+
+ /* PD_RKVENC */
+
+ /* PD_RKVDEC */
+
+ /* PD_PMU_wrapper */
+ COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(8), 12, GFLAGS),
+ GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 0, GFLAGS),
+ GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 1, GFLAGS),
+ GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 2, GFLAGS),
+ GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 3, GFLAGS),
+ GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 4, GFLAGS),
+ GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 6, GFLAGS),
+ COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(8), 15, GFLAGS),
+ COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(8), 14, GFLAGS),
+ GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(8), 13, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+ COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(6), 0, GFLAGS),
+ GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
+ RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(7), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
+ RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(7), 3, GFLAGS),
+
+ INVERTER(0, "pclk_vip", "ext_vip",
+ RK1108_CLKSEL_CON(31), 8, IFLAGS),
+ GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(18), 10, GFLAGS),
+ GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(6), 5, GFLAGS),
+ GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(6), 4, GFLAGS),
+ COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
+ RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 5
+ */
+
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(2), 0, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(8), 0,
+ RK1108_CLKGATE_CON(2), 1, GFLAGS,
+ &rk1108_i2s0_fracmux),
+ GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
+ RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+ RK1108_CLKGATE_CON(2), 3, GFLAGS),
+
+ COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(2), 4, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(9), 0,
+ RK2928_CLKGATE_CON(2), 5, GFLAGS,
+ &rk1108_i2s1_fracmux),
+ GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 6, GFLAGS),
+
+ COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 8, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(10), 0,
+ RK1108_CLKGATE_CON(2), 9, GFLAGS,
+ &rk1108_i2s2_fracmux),
+ GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 10, GFLAGS),
+
+ /* PD_BUS */
+ GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 2, GFLAGS),
+ COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
+ RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
+ RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(1), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
+ RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 4, GFLAGS),
+
+ COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 1, GFLAGS),
+ COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 3, GFLAGS),
+ COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 5, GFLAGS),
+
+ COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(16), 0,
+ RK1108_CLKGATE_CON(3), 2, GFLAGS,
+ &rk1108_uart0_fracmux),
+ COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(17), 0,
+ RK1108_CLKGATE_CON(3), 4, GFLAGS,
+ &rk1108_uart1_fracmux),
+ COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(18), 0,
+ RK1108_CLKGATE_CON(3), 6, GFLAGS,
+ &rk1108_uart2_fracmux),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 10, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 11, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 12, GFLAGS),
+
+ COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 7, GFLAGS),
+ COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 8, GFLAGS),
+ COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 9, GFLAGS),
+ GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 1, GFLAGS),
+ GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 2, GFLAGS),
+ COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 10, GFLAGS),
+ GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 6, GFLAGS),
+ GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 3, GFLAGS),
+ GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 7, GFLAGS),
+ GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 8, GFLAGS),
+ GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 9, GFLAGS),
+
+ GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(14), 0, GFLAGS),
+
+ GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
+ RK1108_CLKGATE_CON(12), 2, GFLAGS),
+ GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 3, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 1, GFLAGS),
+
+ /* PD_DDR */
+ GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 8, GFLAGS),
+ GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 9, GFLAGS),
+ GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+ DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK1108_CLKGATE_CON(10), 9, GFLAGS),
+ GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 4, GFLAGS),
+ GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 5, GFLAGS),
+ GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 6, GFLAGS),
+ GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 11, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 6
+ */
+
+ /* PD_PERI */
+ COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
+ RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 5, GFLAGS),
+ GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(15), 13, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
+ RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 4, GFLAGS),
+ GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(15), 12, GFLAGS),
+
+ GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(4), 1, GFLAGS),
+ GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(4), 2, GFLAGS),
+ COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(15), 11, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK1108_CLKGATE_CON(5), 0, GFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+ RK1108_CLKGATE_CON(5), 2, GFLAGS),
+ DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+ RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+ RK1108_CLKGATE_CON(5), 1, GFLAGS),
+ DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+ RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+
+ COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(5), 3, GFLAGS),
+ GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+
+ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+
+ COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
+ RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 10, GFLAGS),
+ MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+ GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
+ GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
+ GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1),
+
+ MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1),
+};
+
+static const char *const rk1108_critical_clocks[] __initconst = {
+ "aclk_core",
+ "aclk_bus_src_gpll",
+ "aclk_periph",
+ "hclk_periph",
+ "pclk_periph",
+};
+
+static void __init rk1108_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ iounmap(reg_base);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk1108_pll_clks,
+ ARRAY_SIZE(rk1108_pll_clks),
+ RK1108_GRF_SOC_STATUS0);
+ rockchip_clk_register_branches(ctx, rk1108_clk_branches,
+ ARRAY_SIZE(rk1108_clk_branches));
+ rockchip_clk_protect_critical(rk1108_critical_clocks,
+ ARRAY_SIZE(rk1108_critical_clocks));
+
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+ mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+ &rk1108_cpuclk_data, rk1108_cpuclk_rates,
+ ARRAY_SIZE(rk1108_cpuclk_rates));
+
+ rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 1653edd..d67eecc 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -34,6 +34,21 @@
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
+/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RK1108_PLL_CON(x) ((x) * 0x4)
+#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
+#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
+#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
+#define RK1108_GLB_SRST_FST 0x1c0
+#define RK1108_GLB_SRST_SND 0x1c4
+#define RK1108_MISC_CON 0x1cc
+#define RK1108_SDMMC_CON0 0x1d8
+#define RK1108_SDMMC_CON1 0x1dc
+#define RK1108_SDIO_CON0 0x1e0
+#define RK1108_SDIO_CON1 0x1e4
+#define RK1108_EMMC_CON0 0x1e8
+#define RK1108_EMMC_CON1 0x1ec
+
#define RK2928_PLL_CON(x) ((x) * 0x4)
#define RK2928_MODE_CON 0x40
#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/3] clk: rockchip: add dt-binding header for rk1108
From: Shawn Lin @ 2016-11-16 8:49 UTC (permalink / raw)
To: Heiko Stuebner
Cc: Stephen Boyd, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
Andy Yan, Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Lin
In-Reply-To: <1479286163-34789-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add the dt-bindings header for the rk1108, that gets shared
between the clock controller and the clock references in the dts.
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Changes in v3:
- rename PLL name and advance the clk id to save some space
Changes in v2:
- split dt-binding header from clk driver
include/dt-bindings/clock/rk1108-cru.h | 269 +++++++++++++++++++++++++++++++++
1 file changed, 269 insertions(+)
create mode 100644 include/dt-bindings/clock/rk1108-cru.h
diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h
new file mode 100644
index 0000000..b28abb0
--- /dev/null
+++ b/include/dt-bindings/clock/rk1108-cru.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+
+/* pll id */
+#define PLL_APLL 0
+#define PLL_DPLL 1
+#define PLL_GPLL 2
+#define ARMCLK 3
+
+/* sclk gates (special clocks) */
+#define SCLK_SPI0 65
+#define SCLK_NANDC 67
+#define SCLK_SDMMC 68
+#define SCLK_SDIO 69
+#define SCLK_EMMC 71
+#define SCLK_UART0 72
+#define SCLK_UART1 73
+#define SCLK_UART2 74
+#define SCLK_I2S0 75
+#define SCLK_I2S1 76
+#define SCLK_I2S2 77
+#define SCLK_TIMER0 78
+#define SCLK_TIMER1 79
+#define SCLK_SFC 80
+#define SCLK_SDMMC_DRV 81
+#define SCLK_SDIO_DRV 82
+#define SCLK_EMMC_DRV 83
+#define SCLK_SDMMC_SAMPLE 84
+#define SCLK_SDIO_SAMPLE 85
+#define SCLK_EMMC_SAMPLE 86
+
+/* aclk gates */
+#define ACLK_DMAC 192
+#define ACLK_PRE 193
+#define ACLK_CORE 194
+#define ACLK_ENMCORE 195
+
+/* pclk gates */
+#define PCLK_GPIO1 256
+#define PCLK_GPIO2 257
+#define PCLK_GPIO3 258
+#define PCLK_GRF 259
+#define PCLK_I2C1 260
+#define PCLK_I2C2 261
+#define PCLK_I2C3 262
+#define PCLK_SPI 263
+#define PCLK_SFC 264
+#define PCLK_UART0 265
+#define PCLK_UART1 266
+#define PCLK_UART2 267
+#define PCLK_TSADC 268
+#define PCLK_PWM 269
+#define PCLK_TIMER 270
+#define PCLK_PERI 271
+
+/* hclk gates */
+#define HCLK_I2S0_8CH 320
+#define HCLK_I2S1_8CH 321
+#define HCLK_I2S2_2CH 322
+#define HCLK_NANDC 323
+#define HCLK_SDMMC 324
+#define HCLK_SDIO 325
+#define HCLK_EMMC 326
+#define HCLK_PERI 327
+#define HCLK_SFC 328
+
+#define CLK_NR_CLKS (HCLK_SFC + 1)
+
+/* reset id */
+#define SRST_CORE_PO_AD 0
+#define SRST_CORE_AD 1
+#define SRST_L2_AD 2
+#define SRST_CPU_NIU_AD 3
+#define SRST_CORE_PO 4
+#define SRST_CORE 5
+#define SRST_L2 6
+#define SRST_CORE_DBG 8
+#define PRST_DBG 9
+#define RST_DAP 10
+#define PRST_DBG_NIU 11
+#define ARST_STRC_SYS_AD 15
+
+#define SRST_DDRPHY_CLKDIV 16
+#define SRST_DDRPHY 17
+#define PRST_DDRPHY 18
+#define PRST_HDMIPHY 19
+#define PRST_VDACPHY 20
+#define PRST_VADCPHY 21
+#define PRST_MIPI_CSI_PHY 22
+#define PRST_MIPI_DSI_PHY 23
+#define PRST_ACODEC 24
+#define ARST_BUS_NIU 25
+#define PRST_TOP_NIU 26
+#define ARST_INTMEM 27
+#define HRST_ROM 28
+#define ARST_DMAC 29
+#define SRST_MSCH_NIU 30
+#define PRST_MSCH_NIU 31
+
+#define PRST_DDRUPCTL 32
+#define NRST_DDRUPCTL 33
+#define PRST_DDRMON 34
+#define HRST_I2S0_8CH 35
+#define MRST_I2S0_8CH 36
+#define HRST_I2S1_2CH 37
+#define MRST_IS21_2CH 38
+#define HRST_I2S2_2CH 39
+#define MRST_I2S2_2CH 40
+#define HRST_CRYPTO 41
+#define SRST_CRYPTO 42
+#define PRST_SPI 43
+#define SRST_SPI 44
+#define PRST_UART0 45
+#define PRST_UART1 46
+#define PRST_UART2 47
+
+#define SRST_UART0 48
+#define SRST_UART1 49
+#define SRST_UART2 50
+#define PRST_I2C1 51
+#define PRST_I2C2 52
+#define PRST_I2C3 53
+#define SRST_I2C1 54
+#define SRST_I2C2 55
+#define SRST_I2C3 56
+#define PRST_PWM1 58
+#define SRST_PWM1 60
+#define PRST_WDT 61
+#define PRST_GPIO1 62
+#define PRST_GPIO2 63
+
+#define PRST_GPIO3 64
+#define PRST_GRF 65
+#define PRST_EFUSE 66
+#define PRST_EFUSE512 67
+#define PRST_TIMER0 68
+#define SRST_TIMER0 69
+#define SRST_TIMER1 70
+#define PRST_TSADC 71
+#define SRST_TSADC 72
+#define PRST_SARADC 73
+#define SRST_SARADC 74
+#define HRST_SYSBUS 75
+#define PRST_USBGRF 76
+
+#define ARST_PERIPH_NIU 80
+#define HRST_PERIPH_NIU 81
+#define PRST_PERIPH_NIU 82
+#define HRST_PERIPH 83
+#define HRST_SDMMC 84
+#define HRST_SDIO 85
+#define HRST_EMMC 86
+#define HRST_NANDC 87
+#define NRST_NANDC 88
+#define HRST_SFC 89
+#define SRST_SFC 90
+#define ARST_GMAC 91
+#define HRST_OTG 92
+#define SRST_OTG 93
+#define SRST_OTG_ADP 94
+#define HRST_HOST0 95
+
+#define HRST_HOST0_AUX 96
+#define HRST_HOST0_ARB 97
+#define SRST_HOST0_EHCIPHY 98
+#define SRST_HOST0_UTMI 99
+#define SRST_USBPOR 100
+#define SRST_UTMI0 101
+#define SRST_UTMI1 102
+
+#define ARST_VIO0_NIU 102
+#define ARST_VIO1_NIU 103
+#define HRST_VIO_NIU 104
+#define PRST_VIO_NIU 105
+#define ARST_VOP 106
+#define HRST_VOP 107
+#define DRST_VOP 108
+#define ARST_IEP 109
+#define HRST_IEP 110
+#define ARST_RGA 111
+#define HRST_RGA 112
+#define SRST_RGA 113
+#define PRST_CVBS 114
+#define PRST_HDMI 115
+#define SRST_HDMI 116
+#define PRST_MIPI_DSI 117
+
+#define ARST_ISP_NIU 118
+#define HRST_ISP_NIU 119
+#define HRST_ISP 120
+#define SRST_ISP 121
+#define ARST_VIP0 122
+#define HRST_VIP0 123
+#define PRST_VIP0 124
+#define ARST_VIP1 125
+#define HRST_VIP1 126
+#define PRST_VIP1 127
+#define ARST_VIP2 128
+#define HRST_VIP2 129
+#define PRST_VIP2 120
+#define ARST_VIP3 121
+#define HRST_VIP3 122
+#define PRST_VIP4 123
+
+#define PRST_CIF1TO4 124
+#define SRST_CVBS_CLK 125
+#define HRST_CVBS 126
+
+#define ARST_VPU_NIU 140
+#define HRST_VPU_NIU 141
+#define ARST_VPU 142
+#define HRST_VPU 143
+#define ARST_RKVDEC_NIU 144
+#define HRST_RKVDEC_NIU 145
+#define ARST_RKVDEC 146
+#define HRST_RKVDEC 147
+#define SRST_RKVDEC_CABAC 148
+#define SRST_RKVDEC_CORE 149
+#define ARST_RKVENC_NIU 150
+#define HRST_RKVENC_NIU 151
+#define ARST_RKVENC 152
+#define HRST_RKVENC 153
+#define SRST_RKVENC_CORE 154
+
+#define SRST_DSP_CORE 156
+#define SRST_DSP_SYS 157
+#define SRST_DSP_GLOBAL 158
+#define SRST_DSP_OECM 159
+#define PRST_DSP_IOP_NIU 160
+#define ARST_DSP_EPP_NIU 161
+#define ARST_DSP_EDP_NIU 162
+#define PRST_DSP_DBG_NIU 163
+#define PRST_DSP_CFG_NIU 164
+#define PRST_DSP_GRF 165
+#define PRST_DSP_MAILBOX 166
+#define PRST_DSP_INTC 167
+#define PRST_DSP_PFM_MON 169
+#define SRST_DSP_PFM_MON 170
+#define ARST_DSP_EDAP_NIU 171
+
+#define SRST_PMU 172
+#define SRST_PMU_I2C0 173
+#define PRST_PMU_I2C0 174
+#define PRST_PMU_GPIO0 175
+#define PRST_PMU_INTMEM 176
+#define PRST_PMU_PWM0 177
+#define SRST_PMU_PWM0 178
+#define PRST_PMU_GRF 179
+#define SRST_PMU_NIU 180
+#define SRST_PMU_PVTM 181
+#define ARST_DSP_EDP_PERF 184
+#define ARST_DSP_EPP_PERF 185
+
+#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 1/3] dt-bindings: add documentation for rk1108 cru
From: Shawn Lin @ 2016-11-16 8:49 UTC (permalink / raw)
To: Heiko Stuebner
Cc: Stephen Boyd, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
Andy Yan, Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Lin
This adds the dt-binding documentation for the clock and reset unit
found on Rockchip rk1108 SoCs.
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Changes in v3:
- fix mismatch of external clk input name
- add hdmiphy and usbphy clk input
Changes in v2: None
.../bindings/clock/rockchip,rk1108-cru.txt | 59 ++++++++++++++++++++++
1 file changed, 59 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
new file mode 100644
index 0000000..4da1261
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
@@ -0,0 +1,59 @@
+* Rockchip RK1108 Clock and Reset Unit
+
+The RK1108 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,rk1108-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/rk1108-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,
+ - "ext_vip" - external VIP clock - optional
+ - "ext_i2s" - external I2S clock - optional
+ - "ext_gmac" - external GMAC clock - optional
+ - "hdmiphy" - external clock input derived from HDMI PHY - optional
+ - "usbphy" - external clock input derived from USB PHY - optional
+
+Example: Clock controller node:
+
+ cru: cru@20200000 {
+ compatible = "rockchip,rk1108-cru";
+ reg = <0x20200000 0x1000>;
+ rockchip,grf = <&grf>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart0: serial@10230000 {
+ compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+ reg = <0x10230000 0x100>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART0>;
+ };
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH] ARM: zynq: Fix pmu register description coding style
From: Michal Simek @ 2016-11-16 8:32 UTC (permalink / raw)
To: linux-arm-kernel
Cc: julia, Sören Brinkmann, devicetree, monstr, Steffen Trumtrar,
linux-kernel, Peter Crosthwaite, Rob Herring, Rob Herring,
Mark Rutland, Josh Cartwright, Russell King
Drop the space before/after '<' and '>'; and
separate the entries to be a bit more readable.
Reported-by: Julia Cartwright <julia@ni.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 402b5bbe3b5b..f3ac9bfe580e 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -46,7 +46,8 @@
compatible = "arm,cortex-a9-pmu";
interrupts = <0 5 4>, <0 6 4>;
interrupt-parent = <&intc>;
- reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
+ reg = <0xf8891000 0x1000>,
+ <0xf8893000 0x1000>;
};
regulator_vccpint: fixedregulator {
--
1.9.1
^ permalink raw reply related
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16 8:28 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <89535076-4a77-64a5-68d9-ce15e03b8fb3-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
On 16/11/16 10:25, Jaehoon Chung wrote:
> On 11/16/2016 05:09 PM, Adrian Hunter wrote:
>> On 16/11/16 09:53, Jaehoon Chung wrote:
>>> Added Adrian for sdhci.h
>>>
>>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>>> It's not for only sdhci controller.
>>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>>> to mmc_cookie.
>>
>> The cookie is currently host private data, so I don't understand the
>> motivation behind this.
>
> dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
>
> So i think it can be used about both sdhci and dwmmc.
> Is there no reason that add the private dwmmc data?
>
> With these cookie value, update the dwmmc controller for post/pre_req().
>
> https://patchwork.kernel.org/patch/9429287/
So why not define dwmmc cookies in dw_mmc.c ?
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16 8:25 UTC (permalink / raw)
To: Adrian Hunter, linux-mmc
Cc: devicetree, Ulf Hansson, heiko, shawn.lin, robh+dt
In-Reply-To: <ecb4b5d0-4cbf-bf44-3287-f1580b2e990a@intel.com>
On 11/16/2016 05:09 PM, Adrian Hunter wrote:
> On 16/11/16 09:53, Jaehoon Chung wrote:
>> Added Adrian for sdhci.h
>>
>> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>>> It's not for only sdhci controller.
>>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>>> to mmc_cookie.
>
> The cookie is currently host private data, so I don't understand the
> motivation behind this.
dwmmc controller can also use the data->host_cookie. because it's working with post/pre_req().
So i think it can be used about both sdhci and dwmmc.
Is there no reason that add the private dwmmc data?
With these cookie value, update the dwmmc controller for post/pre_req().
https://patchwork.kernel.org/patch/9429287/
Best Regards,
Jaehoon Chung
>
>>>
>>> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
>>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>>> ---
>>> drivers/mmc/host/sdhci.h | 6 ------
>>> include/linux/mmc/core.h | 6 ++++++
>>> 2 files changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>> index 766df17..325663b 100644
>>> --- a/drivers/mmc/host/sdhci.h
>>> +++ b/drivers/mmc/host/sdhci.h
>>> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
>>> /* Allow for a a command request and a data request at the same time */
>>> #define SDHCI_MAX_MRQS 2
>>>
>>> -enum sdhci_cookie {
>>> - COOKIE_UNMAPPED,
>>> - COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */
>>> - COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */
>>> -};
>>> -
>>> struct sdhci_host {
>>> /* Data set by hardware interface driver */
>>> const char *hw_name; /* Hardware bus name */
>>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>>> index 0ce928b..82d707f 100644
>>> --- a/include/linux/mmc/core.h
>>> +++ b/include/linux/mmc/core.h
>>> @@ -118,6 +118,12 @@ struct mmc_command {
>>> struct mmc_request *mrq; /* associated request */
>>> };
>>>
>>> +enum mmc_cookie {
>>> + COOKIE_UNMAPPED,
>>> + COOKIE_PRE_MAPPED, /* mapped by pre_req() of controller */
>>> + COOKIE_MAPPED, /* mapped by prepare_data() of controller */
>>> +};
>>> +
>>> struct mmc_data {
>>> unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
>>> unsigned int timeout_clks; /* data timeout (in clocks) */
>>>
>>
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
>
^ permalink raw reply
* Re: [linux-sunxi] Re: [PATCH v3 1/2] drm/bridge: dumb-vga-dac: Support a VDD regulator supply
From: Archit Taneja @ 2016-11-16 8:17 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: David Airlie, Rob Herring, Maxime Ripard, Mark Rutland, dri-devel,
linux-arm-kernel, linux-kernel, devicetree, linux-sunxi
In-Reply-To: <CAGb2v67LR4KEb0tfGkT8+TqTauNyCMq1n6mRdXsa6TUJV0xncA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi,
On 11/15/2016 08:29 AM, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Nov 2, 2016 at 9:33 AM, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> wrote:
>> On Mon, Oct 31, 2016 at 2:28 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>> On Sat, Oct 29, 2016 at 07:06:10PM +0800, Chen-Yu Tsai wrote:
>>>> Some dumb VGA DACs are active components which require external power.
>>>> Add support for specifying a regulator as its power supply.
>>>>
>>>> Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
>>>> ---
>>>> .../bindings/display/bridge/dumb-vga-dac.txt | 2 ++
>>>
>>> For the binding,
>>>
>>> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>
> Any comments on this patch from the DRM people?
A comment below.
>
> ChenYu
>
>>>
>>> One code comment below...
>>>
>>>> drivers/gpu/drm/bridge/dumb-vga-dac.c | 35 ++++++++++++++++++++++
>>>> 2 files changed, 37 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> index 003bc246a270..164cbb15f04c 100644
>>>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> @@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
>>>> - Video port 0 for RGB input
>>>> - Video port 1 for VGA output
>>>>
>>>> +Optional properties:
>>>> +- vdd-supply: Power supply for DAC
>>>>
>>>> Example
>>>> -------
>>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> index afec232185a7..59781e031220 100644
>>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> @@ -12,6 +12,7 @@
>>>>
>>>> #include <linux/module.h>
>>>> #include <linux/of_graph.h>
>>>> +#include <linux/regulator/consumer.h>
>>>>
>>>> #include <drm/drmP.h>
>>>> #include <drm/drm_atomic_helper.h>
>>>> @@ -23,6 +24,7 @@ struct dumb_vga {
>>>> struct drm_connector connector;
>>>>
>>>> struct i2c_adapter *ddc;
>>>> + struct regulator *vdd;
>>>> };
>>>>
>>>> static inline struct dumb_vga *
>>>> @@ -124,8 +126,33 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
>>>> return 0;
>>>> }
>>>>
>>>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>>>> +{
>>>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> + int ret;
>>>> +
>>>> + if (!IS_ERR(vga->vdd)) {
>>>
>>> if (IS_ERR())
>>> return;
>>>
>>> ...will save some intentation.
>>
>> I thought about that, though if someone were to add more stuff to
>> this, such as an enable GPIO, they might have to rework it. A standalone
>> block of code would be easier to work with. I'm OK either way though.
>>
>> ChenYu
>>
>>>
>>>> + ret = regulator_enable(vga->vdd);
>>>> +
>>>> + if (ret) {
>>>> + DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
>>>> + return;
>>>> + }
>>>> + }
>>>> +}
>>>> +
>>>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>>>> +{
>>>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> +
>>>> + if (!IS_ERR(vga->vdd))
>>>> + regulator_disable(vga->vdd);
>>>> +}
>>>> +
>>>> static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>>>> .attach = dumb_vga_attach,
>>>> + .enable = dumb_vga_enable,
>>>> + .disable = dumb_vga_disable,
>>>> };
>>>>
>>>> static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>>>> @@ -169,6 +196,14 @@ static int dumb_vga_probe(struct platform_device *pdev)
>>>> return -ENOMEM;
>>>> platform_set_drvdata(pdev, vga);
>>>>
>>>> + vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
>>>> + if (IS_ERR(vga->vdd)) {
>>>> + ret = PTR_ERR(vga->vdd);
>>>> + if (ret == -EPROBE_DEFER)
>>>> + return -EPROBE_DEFER;
>>>> + dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
A cleaner way would be to set vga->vdd to NULL here, and do:
int ret = 0;
if (vga->vdd)
ret = regulator_enable(vga->vdd);
if (ret) {
...
return;
}
/* if a gpio is added later */
if (vga->gpio)
ret = gpiod_set_value_cansleep(vga->gpio, 1);
if (ret) {
...
return;
}
...
We don't really care what error code is contained in vga->vdd once we have
identified whether we got a regulator or not.
The same thing can be done for ddc too, but that can done left for later.
If you're okay with the suggestion, can you re-spin a patch?
Thanks,
Archit
>>>> + }
>>>> +
>>>> vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>>>> if (IS_ERR(vga->ddc)) {
>>>> if (PTR_ERR(vga->ddc) == -ENODEV) {
>>>> --
>>>> 2.9.3
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
>>> For more options, visit https://groups.google.com/d/optout.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Adrian Hunter @ 2016-11-16 8:09 UTC (permalink / raw)
To: Jaehoon Chung, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <12405f58-695d-03d8-407f-d7471e93a6de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
On 16/11/16 09:53, Jaehoon Chung wrote:
> Added Adrian for sdhci.h
>
> On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
>> It's not for only sdhci controller.
>> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
>> to mmc_cookie.
The cookie is currently host private data, so I don't understand the
motivation behind this.
>>
>> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
>> ---
>> drivers/mmc/host/sdhci.h | 6 ------
>> include/linux/mmc/core.h | 6 ++++++
>> 2 files changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 766df17..325663b 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
>> /* Allow for a a command request and a data request at the same time */
>> #define SDHCI_MAX_MRQS 2
>>
>> -enum sdhci_cookie {
>> - COOKIE_UNMAPPED,
>> - COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */
>> - COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */
>> -};
>> -
>> struct sdhci_host {
>> /* Data set by hardware interface driver */
>> const char *hw_name; /* Hardware bus name */
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> index 0ce928b..82d707f 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -118,6 +118,12 @@ struct mmc_command {
>> struct mmc_request *mrq; /* associated request */
>> };
>>
>> +enum mmc_cookie {
>> + COOKIE_UNMAPPED,
>> + COOKIE_PRE_MAPPED, /* mapped by pre_req() of controller */
>> + COOKIE_MAPPED, /* mapped by prepare_data() of controller */
>> +};
>> +
>> struct mmc_data {
>> unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
>> unsigned int timeout_clks; /* data timeout (in clocks) */
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH resend v4] i2c: hibvt: add Hisilicon BVT I2C controller driver
From: Jiancheng Xue @ 2016-11-16 8:00 UTC (permalink / raw)
To: wsa
Cc: Pan Wen, robh+dt, mark.rutland, linux-i2c, devicetree,
linux-kernel, howell.yang, jalen.hsu, lvkuanliang, suwenping,
raojun, kevin.lixu
In-Reply-To: <20161021081709.7307-1-wenpan@hisilicon.com>
Hi Wolfram,
On 2016/10/21 16:17, Pan Wen wrote:
> add Hisilicon BVT I2C controller driver support.
>
> Signed-off-by: Pan Wen <wenpan@hisilicon.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> change log
> v4:
> Modify the default frequency to 100KHz.
> v3:
> Add a SoC specific compatible string.
> v2:
> 1)Fixed a compile error.
> 2)Dropped the clock-names property.
> .../devicetree/bindings/i2c/i2c-hibvt.txt | 24 +
> drivers/i2c/busses/Kconfig | 10 +
> drivers/i2c/busses/Makefile | 1 +
> drivers/i2c/busses/i2c-hibvt.c | 737 +++++++++++++++++++++
> 4 files changed, 772 insertions(+)
Could you give us some comments on this patch?
If there are some issues about it, please let us know.
Thank you very much!
Best Regards,
Jiancheng
> create mode 100644 Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
> create mode 100644 drivers/i2c/busses/i2c-hibvt.c
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
> new file mode 100644
> index 0000000..db3d2e2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt
> @@ -0,0 +1,24 @@
> +Hisilicon BVT I2C master controller
> +
> +Required properties:
> +- compatible: should be "hisilicon,hibvt-i2c" and one of the following:
> + "hisilicon,hi3516cv300-i2c"
> +- reg: physical base address of the controller and length of memory mapped.
> + region.
> +- interrupts: interrupt number to the cpu.
> +- clocks: phandles to input clocks.
> +
> +Optional properties:
> +- clock-frequency: Desired I2C bus frequency in Hz, otherwise defaults to 100000.
> +
> +Other properties:
> +see Documentation/devicetree/bindings/i2c/i2c.txt.
> +
> +Examples:
> +i2c_bus0: i2c@12110000 {
> + compatible = "hisilicon,hi3516cv300-i2c", "hisilicon,hibvt-i2c";
> + reg = <0x12110000 0x100>;
> + interrupts = <20>;
> + clocks = <&crg_ctrl HI3516CV300_APB_CLK>;
> + clock-frequency = <100000>;
> +};
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 5c3993b..fc1b679 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -555,6 +555,16 @@ config I2C_GPIO
> This is a very simple bitbanging I2C driver utilizing the
> arch-neutral GPIO API to control the SCL and SDA lines.
>
> +config I2C_HIBVT
> + tristate "Hisilicon BVT I2C Controller"
> + depends on ARCH_HISI
> + help
> + Say Y here to include support for Hisilicon BVT I2C controller in the
> + Hisilicon BVT SoCs.
> +
> + This driver can also be built as a module. If so, the module
> + will be called i2c-hibvt.
> +
> config I2C_HIGHLANDER
> tristate "Highlander FPGA SMBus interface"
> depends on SH_HIGHLANDER
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 37f2819..42ef2e0 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -51,6 +51,7 @@ obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
> obj-$(CONFIG_I2C_EMEV2) += i2c-emev2.o
> obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o
> obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
> +obj-$(CONFIG_I2C_HIBVT) += i2c-hibvt.o
> obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
> obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o
> obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
> diff --git a/drivers/i2c/busses/i2c-hibvt.c b/drivers/i2c/busses/i2c-hibvt.c
> new file mode 100644
> index 0000000..e8af63e
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-hibvt.c
> @@ -0,0 +1,737 @@
> +/*
> + * Hisilicon BVT I2C Controller Driver
> + *
> + * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
> + *
> + * Authors: wenpan@hisilicon.com
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +/*
> + * I2C Registers offsets
> + */
> +#define HIBVT_I2C_GLB 0x0
> +#define HIBVT_I2C_SCL_H 0x4
> +#define HIBVT_I2C_SCL_L 0x8
> +#define HIBVT_I2C_DATA1 0x10
> +#define HIBVT_I2C_TXF 0x20
> +#define HIBVT_I2C_RXF 0x24
> +#define HIBVT_I2C_CMD_BASE 0x30
> +#define HIBVT_I2C_LOOP1 0xb0
> +#define HIBVT_I2C_DST1 0xb4
> +#define HIBVT_I2C_TX_WATER 0xc8
> +#define HIBVT_I2C_RX_WATER 0xcc
> +#define HIBVT_I2C_CTRL1 0xd0
> +#define HIBVT_I2C_STAT 0xd8
> +#define HIBVT_I2C_INTR_RAW 0xe0
> +#define HIBVT_I2C_INTR_EN 0xe4
> +#define HIBVT_I2C_INTR_STAT 0xe8
> +
> +/*
> + * I2C Global Config Register -- HIBVT_I2C_GLB
> + */
> +#define GLB_EN_MASK BIT(0)
> +#define GLB_SDA_HOLD_MASK GENMASK(23, 8)
> +#define GLB_SDA_HOLD_SHIFT (8)
> +
> +/*
> + * I2C Timing CMD Register -- HIBVT_I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31)
> + */
> +#define CMD_EXIT 0x0
> +#define CMD_TX_S 0x1
> +#define CMD_TX_D1_2 0x4
> +#define CMD_TX_D1_1 0x5
> +#define CMD_TX_FIFO 0x9
> +#define CMD_RX_FIFO 0x12
> +#define CMD_RX_ACK 0x13
> +#define CMD_IGN_ACK 0x15
> +#define CMD_TX_ACK 0x16
> +#define CMD_TX_NACK 0x17
> +#define CMD_JMP1 0x18
> +#define CMD_UP_TXF 0x1d
> +#define CMD_TX_RS 0x1e
> +#define CMD_TX_P 0x1f
> +
> +/*
> + * I2C Control Register 1 -- HIBVT_I2C_CTRL1
> + */
> +#define CTRL1_CMD_START_MASK BIT(0)
> +
> +/*
> + * I2C Status Register -- HIBVT_I2C_STAT
> + */
> +#define STAT_RXF_NOE_MASK BIT(16) /* RX FIFO not empty flag */
> +#define STAT_TXF_NOF_MASK BIT(19) /* TX FIFO not full flag */
> +
> +
> +/*
> + * I2C Interrupt status and mask Register --
> + * HIBVT_I2C_INTR_RAW, HIBVT_I2C_STAT, HIBVT_I2C_INTR_STAT
> + */
> +#define INTR_ABORT_MASK (BIT(0) | BIT(11))
> +#define INTR_RX_MASK BIT(2)
> +#define INTR_TX_MASK BIT(4)
> +#define INTR_CMD_DONE_MASK BIT(12)
> +#define INTR_USE_MASK (INTR_ABORT_MASK \
> + |INTR_RX_MASK \
> + | INTR_TX_MASK \
> + | INTR_CMD_DONE_MASK)
> +#define INTR_ALL_MASK GENMASK(31, 0)
> +
> +#define I2C_DEFAULT_FREQUENCY 100000
> +#define I2C_TXF_DEPTH 64
> +#define I2C_RXF_DEPTH 64
> +#define I2C_TXF_WATER 32
> +#define I2C_RXF_WATER 32
> +#define I2C_WAIT_TIMEOUT 0x10000
> +#define I2C_IRQ_TIMEOUT (msecs_to_jiffies(1000))
> +
> +
> +struct hibvt_i2c_dev {
> + struct device *dev;
> + struct i2c_adapter adap;
> + void __iomem *base;
> + struct clk *clk;
> + int irq;
> +
> + unsigned int freq;
> + struct i2c_msg *msg;
> + unsigned int msg_num;
> + unsigned int msg_idx;
> + unsigned int msg_buf_ptr;
> + struct completion msg_complete;
> +
> + spinlock_t lock;
> + int status;
> +};
> +
> +static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int val;
> +
> + val = readl(i2c->base + HIBVT_I2C_GLB);
> + val &= ~GLB_EN_MASK;
> + writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int val;
> +
> + val = readl(i2c->base + HIBVT_I2C_GLB);
> + val |= GLB_EN_MASK;
> + writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c,
> + unsigned int flag)
> +{
> + writel(flag, i2c->base + HIBVT_I2C_INTR_EN);
> +}
> +
> +static inline void hibvt_i2c_disable_irq(struct hibvt_i2c_dev *i2c,
> + unsigned int flag)
> +{
> + unsigned int val;
> +
> + val = readl(i2c->base + HIBVT_I2C_INTR_EN);
> + val &= ~flag;
> + writel(val, i2c->base + HIBVT_I2C_INTR_EN);
> +}
> +
> +static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int val;
> +
> + val = readl(i2c->base + HIBVT_I2C_INTR_STAT);
> + writel(INTR_ALL_MASK, i2c->base + HIBVT_I2C_INTR_RAW);
> +
> + return val;
> +}
> +
> +static inline void hibvt_i2c_cmdreg_set(struct hibvt_i2c_dev *i2c,
> + unsigned int cmd, unsigned int *offset)
> +{
> + dev_dbg(i2c->dev, "hii2c reg: offset=0x%x, cmd=0x%x...\n",
> + *offset * 4, cmd);
> + writel(cmd, i2c->base + HIBVT_I2C_CMD_BASE + *offset * 4);
> + (*offset)++;
> +}
> +
> +/*
> + * config i2c slave addr
> + */
> +static inline void hibvt_i2c_set_addr(struct hibvt_i2c_dev *i2c)
> +{
> + struct i2c_msg *msg = i2c->msg;
> + u16 addr;
> +
> + if (msg->flags & I2C_M_TEN) {
> + /* First byte is 11110XX0 where XX is upper 2 bits */
> + addr = ((msg->addr & 0x300) << 1) | 0xf000;
> + if (msg->flags & I2C_M_RD)
> + addr |= 1 << 8;
> +
> + /* Second byte is the remaining 8 bits */
> + addr |= msg->addr & 0xff;
> + } else {
> + addr = (msg->addr & 0x7f) << 1;
> + if (msg->flags & I2C_M_RD)
> + addr |= 1;
> + }
> +
> + writel(addr, i2c->base + HIBVT_I2C_DATA1);
> +}
> +
> +/*
> + * Start command sequence
> + */
> +static inline void hibvt_i2c_start_cmd(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int val;
> +
> + val = readl(i2c->base + HIBVT_I2C_CTRL1);
> + val |= CTRL1_CMD_START_MASK;
> + writel(val, i2c->base + HIBVT_I2C_CTRL1);
> +}
> +
> +static int hibvt_i2c_wait_rx_noempty(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int time_cnt = 0;
> + unsigned int val;
> +
> + do {
> + val = readl(i2c->base + HIBVT_I2C_STAT);
> + if (val & STAT_RXF_NOE_MASK)
> + return 0;
> +
> + udelay(50);
> + } while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> + dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
> + readl(i2c->base + HIBVT_I2C_INTR_RAW), val);
> + return -EIO;
> +}
> +
> +static int hibvt_i2c_wait_tx_nofull(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int time_cnt = 0;
> + unsigned int val;
> +
> + do {
> + val = readl(i2c->base + HIBVT_I2C_STAT);
> + if (val & STAT_TXF_NOF_MASK)
> + return 0;
> +
> + udelay(50);
> + } while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> + dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
> + readl(i2c->base + HIBVT_I2C_INTR_RAW), val);
> + return -EIO;
> +}
> +
> +static int hibvt_i2c_wait_idle(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int time_cnt = 0;
> + unsigned int val;
> +
> + do {
> + val = readl(i2c->base + HIBVT_I2C_INTR_RAW);
> + if (val & (INTR_ABORT_MASK)) {
> + dev_err(i2c->dev, "wait idle abort!, RIS: 0x%x\n",
> + val);
> + return -EIO;
> + }
> +
> + if (val & INTR_CMD_DONE_MASK)
> + return 0;
> +
> + udelay(50);
> + } while (time_cnt++ < I2C_WAIT_TIMEOUT);
> +
> + dev_err(i2c->dev, "wait idle timeout, RIS: 0x%x, SR: 0x%x\n",
> + val, readl(i2c->base + HIBVT_I2C_STAT));
> +
> + return -EIO;
> +}
> +
> +static void hibvt_i2c_set_freq(struct hibvt_i2c_dev *i2c)
> +{
> + unsigned int max_freq, freq;
> + unsigned int clk_rate;
> + unsigned int val, sda_hold;
> +
> + freq = i2c->freq;
> + clk_rate = clk_get_rate(i2c->clk);
> + max_freq = clk_rate >> 1;
> +
> + if (freq > max_freq) {
> + i2c->freq = max_freq;
> + freq = i2c->freq;
> + }
> +
> + if (freq <= 100000) {
> + val = clk_rate / (freq * 2) - 1;
> + writel(val, i2c->base + HIBVT_I2C_SCL_H);
> + writel(val, i2c->base + HIBVT_I2C_SCL_L);
> + } else {
> + val = (clk_rate * 36) / (freq * 100);
> + writel(val, i2c->base + HIBVT_I2C_SCL_H);
> + val = (clk_rate * 64) / (freq * 100);
> + writel(val, i2c->base + HIBVT_I2C_SCL_L);
> + }
> +
> + sda_hold = val * 3 / 10;
> + sda_hold = (sda_hold << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK;
> + val = readl(i2c->base + HIBVT_I2C_GLB);
> + val &= ~GLB_SDA_HOLD_MASK;
> + val |= sda_hold;
> + writel(val, i2c->base + HIBVT_I2C_GLB);
> +}
> +
> +/*
> + * set i2c controller TX and RX FIFO water
> + */
> +static inline void hibvt_i2c_set_water(struct hibvt_i2c_dev *i2c)
> +{
> + writel(I2C_TXF_WATER, i2c->base + HIBVT_I2C_TX_WATER);
> + writel(I2C_RXF_WATER, i2c->base + HIBVT_I2C_RX_WATER);
> +}
> +
> +/*
> + * initialise the controller, set i2c bus interface freq
> + */
> +static void hibvt_i2c_hw_init(struct hibvt_i2c_dev *i2c)
> +{
> + hibvt_i2c_disable(i2c);
> + hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> + hibvt_i2c_set_freq(i2c);
> + hibvt_i2c_set_water(i2c);
> +}
> +
> +/*
> + * hibvt_i2c_cfg_cmd - config i2c controller command sequence
> + *
> + * After all the timing command is configured,
> + * and then start the command, you can i2c communication,
> + * and then only need to read and write i2c fifo.
> + */
> +static void hibvt_i2c_cfg_cmd(struct hibvt_i2c_dev *i2c)
> +{
> + struct i2c_msg *msg = i2c->msg;
> + int offset = 0;
> +
> + if (i2c->msg_idx == 0)
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_S, &offset);
> + else
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_RS, &offset);
> +
> + if (msg->flags & I2C_M_TEN) {
> + if (i2c->msg_idx == 0) {
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
> + } else {
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
> + }
> + } else {
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
> + }
> +
> + if (msg->flags & I2C_M_IGNORE_NAK)
> + hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
> + else
> + hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
> +
> + if (msg->flags & I2C_M_RD) {
> + if (msg->len >= 2) {
> + writel(offset, i2c->base + HIBVT_I2C_DST1);
> + writel(msg->len - 2, i2c->base + HIBVT_I2C_LOOP1);
> + hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset);
> + hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
> + }
> + hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset);
> + } else {
> + writel(offset, i2c->base + HIBVT_I2C_DST1);
> + writel(msg->len - 1, i2c->base + HIBVT_I2C_LOOP1);
> + hibvt_i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset);
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset);
> +
> + if (msg->flags & I2C_M_IGNORE_NAK)
> + hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
> + else
> + hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
> +
> + hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
> + }
> +
> + if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) {
> + dev_dbg(i2c->dev, "run to %s %d...TX STOP\n",
> + __func__, __LINE__);
> + hibvt_i2c_cmdreg_set(i2c, CMD_TX_P, &offset);
> + }
> +
> + hibvt_i2c_cmdreg_set(i2c, CMD_EXIT, &offset);
> +}
> +
> +static int hibvt_i2c_polling_xfer_one_msg(struct hibvt_i2c_dev *i2c)
> +{
> + int status;
> + unsigned int val;
> + struct i2c_msg *msg = i2c->msg;
> +
> + dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
> + __func__, __LINE__, msg->flags, msg->len);
> +
> + hibvt_i2c_enable(i2c);
> + hibvt_i2c_clr_irq(i2c);
> + hibvt_i2c_set_addr(i2c);
> + hibvt_i2c_cfg_cmd(i2c);
> + hibvt_i2c_start_cmd(i2c);
> +
> + i2c->msg_buf_ptr = 0;
> +
> + if (msg->flags & I2C_M_RD) {
> + while (i2c->msg_buf_ptr < msg->len) {
> + status = hibvt_i2c_wait_rx_noempty(i2c);
> + if (status)
> + goto end;
> +
> + val = readl(i2c->base + HIBVT_I2C_RXF);
> + msg->buf[i2c->msg_buf_ptr] = val;
> + i2c->msg_buf_ptr++;
> +
> + }
> + } else {
> + while (i2c->msg_buf_ptr < msg->len) {
> + status = hibvt_i2c_wait_tx_nofull(i2c);
> + if (status)
> + goto end;
> +
> + val = msg->buf[i2c->msg_buf_ptr];
> + writel(val, i2c->base + HIBVT_I2C_TXF);
> + i2c->msg_buf_ptr++;
> + }
> + }
> +
> + status = hibvt_i2c_wait_idle(i2c);
> +end:
> + hibvt_i2c_disable(i2c);
> +
> + return status;
> +}
> +
> +static irqreturn_t hibvt_i2c_isr(int irq, void *dev_id)
> +{
> + struct hibvt_i2c_dev *i2c = dev_id;
> + unsigned int irq_status;
> + struct i2c_msg *msg = i2c->msg;
> +
> + spin_lock(&i2c->lock);
> +
> + irq_status = hibvt_i2c_clr_irq(i2c);
> + dev_dbg(i2c->dev, "%s RIS: 0x%x\n", __func__, irq_status);
> +
> + if (!irq_status) {
> + dev_dbg(i2c->dev, "no irq\n");
> + goto end;
> + }
> +
> + if (irq_status & INTR_ABORT_MASK) {
> + dev_err(i2c->dev, "irq handle abort, RIS: 0x%x\n",
> + irq_status);
> + i2c->status = -EIO;
> + hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +
> + complete(&i2c->msg_complete);
> + goto end;
> + }
> +
> + if (msg->flags & I2C_M_RD) {
> + while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_RXF_NOE_MASK)
> + && (i2c->msg_buf_ptr < msg->len)) {
> + msg->buf[i2c->msg_buf_ptr] =
> + readl(i2c->base + HIBVT_I2C_RXF);
> + i2c->msg_buf_ptr++;
> + }
> + } else {
> + while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_TXF_NOF_MASK)
> + && (i2c->msg_buf_ptr < msg->len)) {
> + writel(msg->buf[i2c->msg_buf_ptr],
> + i2c->base + HIBVT_I2C_TXF);
> + i2c->msg_buf_ptr++;
> + }
> + }
> +
> + if (i2c->msg_buf_ptr >= msg->len)
> + hibvt_i2c_disable_irq(i2c, INTR_TX_MASK | INTR_RX_MASK);
> +
> + if (irq_status & INTR_CMD_DONE_MASK) {
> + dev_dbg(i2c->dev, "cmd done\n");
> + i2c->status = 0;
> + hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> +
> + complete(&i2c->msg_complete);
> + }
> +
> +end:
> + spin_unlock(&i2c->lock);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int hibvt_i2c_interrupt_xfer_one_msg(struct hibvt_i2c_dev *i2c)
> +{
> + int status;
> + struct i2c_msg *msg = i2c->msg;
> + unsigned long timeout;
> + unsigned long flags;
> +
> + dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
> + __func__, __LINE__, msg->flags, msg->len);
> +
> + reinit_completion(&i2c->msg_complete);
> + i2c->msg_buf_ptr = 0;
> + i2c->status = -EIO;
> +
> + spin_lock_irqsave(&i2c->lock, flags);
> + hibvt_i2c_enable(i2c);
> + hibvt_i2c_clr_irq(i2c);
> + if (msg->flags & I2C_M_RD)
> + hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_TX_MASK);
> + else
> + hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_RX_MASK);
> +
> + hibvt_i2c_set_addr(i2c);
> + hibvt_i2c_cfg_cmd(i2c);
> + hibvt_i2c_start_cmd(i2c);
> + spin_unlock_irqrestore(&i2c->lock, flags);
> +
> + timeout = wait_for_completion_timeout(&i2c->msg_complete,
> + I2C_IRQ_TIMEOUT);
> +
> + if (timeout == 0) {
> + hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK);
> + status = -EIO;
> + dev_err(i2c->dev, "%s timeout\n",
> + msg->flags & I2C_M_RD ? "rx" : "tx");
> + } else {
> + status = i2c->status;
> + }
> +
> + hibvt_i2c_disable(i2c);
> +
> + return status;
> +}
> +
> +/*
> + * Master transfer function
> + */
> +static int hibvt_i2c_xfer(struct i2c_adapter *adap,
> + struct i2c_msg *msgs, int num)
> +{
> + struct hibvt_i2c_dev *i2c = i2c_get_adapdata(adap);
> + int status;
> +
> + if (!msgs) {
> + dev_err(i2c->dev, "msgs == NULL\n");
> + return -EIO;
> + }
> +
> + i2c->msg = msgs;
> + i2c->msg_num = num;
> + i2c->msg_idx = 0;
> +
> + if (i2c->irq >= 0) {
> + while (i2c->msg_idx < i2c->msg_num) {
> + status = hibvt_i2c_interrupt_xfer_one_msg(i2c);
> + if (status)
> + break;
> +
> + i2c->msg++;
> + i2c->msg_idx++;
> + }
> + } else {
> + while (i2c->msg_idx < i2c->msg_num) {
> + status = hibvt_i2c_polling_xfer_one_msg(i2c);
> + if (status)
> + break;
> +
> + i2c->msg++;
> + i2c->msg_idx++;
> + }
> + }
> +
> + if (!status || i2c->msg_idx > 0)
> + status = i2c->msg_idx;
> +
> + return status;
> +}
> +
> +static u32 hibvt_i2c_func(struct i2c_adapter *adap)
> +{
> + return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR
> + | I2C_FUNC_PROTOCOL_MANGLING;
> +}
> +
> +static const struct i2c_algorithm hibvt_i2c_algo = {
> + .master_xfer = hibvt_i2c_xfer,
> + .functionality = hibvt_i2c_func,
> +};
> +
> +static int hibvt_i2c_probe(struct platform_device *pdev)
> +{
> + int status;
> + struct hibvt_i2c_dev *i2c;
> + struct i2c_adapter *adap;
> + struct resource *res;
> +
> + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
> + if (!i2c)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, i2c);
> + i2c->dev = &pdev->dev;
> + spin_lock_init(&i2c->lock);
> + init_completion(&i2c->msg_complete);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + i2c->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(i2c->base)) {
> + dev_err(i2c->dev, "cannot ioremap resource\n");
> + return -ENOMEM;
> + }
> +
> + i2c->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(i2c->clk)) {
> + dev_err(i2c->dev, "cannot get clock\n");
> + return -ENOENT;
> + }
> + clk_prepare_enable(i2c->clk);
> +
> + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> + &i2c->freq)) {
> + dev_warn(i2c->dev, "setting default clock-frequency@%dHz\n",
> + I2C_DEFAULT_FREQUENCY);
> + i2c->freq = I2C_DEFAULT_FREQUENCY;
> + }
> +
> + /* i2c controller initialization, disable interrupt */
> + hibvt_i2c_hw_init(i2c);
> +
> + i2c->irq = platform_get_irq(pdev, 0);
> + status = devm_request_irq(&pdev->dev, i2c->irq, hibvt_i2c_isr,
> + IRQF_SHARED, dev_name(&pdev->dev), i2c);
> + if (status) {
> + dev_dbg(i2c->dev, "falling back to polling mode");
> + i2c->irq = -1;
> + }
> +
> + adap = &i2c->adap;
> + i2c_set_adapdata(adap, i2c);
> + adap->owner = THIS_MODULE;
> + strlcpy(adap->name, "hibvt-i2c", sizeof(adap->name));
> + adap->dev.parent = &pdev->dev;
> + adap->dev.of_node = pdev->dev.of_node;
> + adap->algo = &hibvt_i2c_algo;
> +
> + /* Add the i2c adapter */
> + status = i2c_add_adapter(adap);
> + if (status) {
> + dev_err(i2c->dev, "failed to add bus to i2c core\n");
> + goto err_add_adapter;
> + }
> +
> + dev_info(i2c->dev, "%s%d@%dhz registered\n",
> + adap->name, adap->nr, i2c->freq);
> +
> + return 0;
> +
> +err_add_adapter:
> + clk_disable_unprepare(i2c->clk);
> + return status;
> +}
> +
> +static int hibvt_i2c_remove(struct platform_device *pdev)
> +{
> + struct hibvt_i2c_dev *i2c = platform_get_drvdata(pdev);
> +
> + clk_disable_unprepare(i2c->clk);
> + i2c_del_adapter(&i2c->adap);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int hibvt_i2c_suspend(struct device *dev)
> +{
> + struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev);
> +
> + i2c_lock_adapter(&i2c->adap);
> + clk_disable_unprepare(i2c->clk);
> + i2c_unlock_adapter(&i2c->adap);
> +
> + return 0;
> +}
> +
> +static int hibvt_i2c_resume(struct device *dev)
> +{
> + struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev);
> +
> + i2c_lock_adapter(&i2c->adap);
> + clk_prepare_enable(i2c->clk);
> + hibvt_i2c_hw_init(i2c);
> + i2c_unlock_adapter(&i2c->adap);
> +
> + return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(hibvt_i2c_dev_pm, hibvt_i2c_suspend,
> + hibvt_i2c_resume);
> +
> +static const struct of_device_id hibvt_i2c_match[] = {
> + { .compatible = "hisilicon,hibvt-i2c"},
> + { .compatible = "hisilicon,hi3516cv300-i2c"},
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, hibvt_i2c_match);
> +
> +static struct platform_driver hibvt_i2c_driver = {
> + .driver = {
> + .name = "hibvt-i2c",
> + .of_match_table = hibvt_i2c_match,
> + .pm = &hibvt_i2c_dev_pm,
> + },
> + .probe = hibvt_i2c_probe,
> + .remove = hibvt_i2c_remove,
> +};
> +
> +module_platform_driver(hibvt_i2c_driver);
> +
> +MODULE_AUTHOR("Pan Wen, <wenpan@hisilicon.com>");
> +MODULE_DESCRIPTION("HISILICON BVT I2C Bus driver");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply
* Re: [PATCHv2 06/10] mmc: core: move the cookie's enum values from sdhci.h to mmc.h
From: Jaehoon Chung @ 2016-11-16 7:53 UTC (permalink / raw)
To: linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Ulf Hansson,
heiko-4mtYJXux2i+zQB+pC5nmwQ, shawn.lin-TNX95d0MmH7DzftRWevZcw,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Adrian Hunter
In-Reply-To: <20161115101232.3854-7-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Added Adrian for sdhci.h
On 11/15/2016 07:12 PM, Jaehoon Chung wrote:
> It's not for only sdhci controller.
> So it can be moved from sdhci.h to mmc.h. And renamed from sdhci_cookie
> to mmc_cookie.
>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Tested-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> ---
> drivers/mmc/host/sdhci.h | 6 ------
> include/linux/mmc/core.h | 6 ++++++
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 766df17..325663b 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -321,12 +321,6 @@ struct sdhci_adma2_64_desc {
> /* Allow for a a command request and a data request at the same time */
> #define SDHCI_MAX_MRQS 2
>
> -enum sdhci_cookie {
> - COOKIE_UNMAPPED,
> - COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */
> - COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */
> -};
> -
> struct sdhci_host {
> /* Data set by hardware interface driver */
> const char *hw_name; /* Hardware bus name */
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 0ce928b..82d707f 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -118,6 +118,12 @@ struct mmc_command {
> struct mmc_request *mrq; /* associated request */
> };
>
> +enum mmc_cookie {
> + COOKIE_UNMAPPED,
> + COOKIE_PRE_MAPPED, /* mapped by pre_req() of controller */
> + COOKIE_MAPPED, /* mapped by prepare_data() of controller */
> +};
> +
> struct mmc_data {
> unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
> unsigned int timeout_clks; /* data timeout (in clocks) */
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v7 08/14] mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
From: Adrian Hunter @ 2016-11-16 7:42 UTC (permalink / raw)
To: Ritesh Harjani, Stephen Boyd, ulf.hansson
Cc: linux-mmc, shawn.lin, andy.gross, devicetree, linux-clk,
david.brown, linux-arm-msm, georgi.djakov, alex.lemberg,
mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman, david.griego,
stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <d723b9fb-0cfc-e72b-ad78-36c8b996b012@codeaurora.org>
On 16/11/16 06:42, Ritesh Harjani wrote:
> Hi,
>
> On 11/15/2016 10:40 AM, Ritesh Harjani wrote:
>> Hi Stephen/Adrian,
>>
>> On 11/15/2016 1:07 AM, Stephen Boyd wrote:
>>> On 11/14, Ritesh Harjani wrote:
>>>> @@ -577,6 +578,90 @@ static unsigned int
>>>> sdhci_msm_get_min_clock(struct sdhci_host *host)
>>>> return SDHCI_MSM_MIN_CLOCK;
>>>> }
>>>>
>>>> +/**
>>>> + * __sdhci_msm_set_clock - sdhci_msm clock control.
>>>> + *
>>>> + * Description:
>>>> + * Implement MSM version of sdhci_set_clock.
>>>> + * This is required since MSM controller does not
>>>> + * use internal divider and instead directly control
>>>> + * the GCC clock as per HW recommendation.
>>>> + **/
>>>> +void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>>>> +{
>>>> + u16 clk;
>>>> + unsigned long timeout;
>>>> +
>>>> + /*
>>>> + * Keep actual_clock as zero -
>>>> + * - since there is no divider used so no need of having
>>>> actual_clock.
>>>> + * - MSM controller uses SDCLK for data timeout calculation. If
>>>> + * actual_clock is zero, host->clock is taken for calculation.
>>>> + */
>>>> + host->mmc->actual_clock = 0;
>>>> +
>>>> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> + if (clock == 0)
>>>> + return;
>>>> +
>>>> + /*
>>>> + * MSM controller do not use clock divider.
>>>> + * Thus read SDHCI_CLOCK_CONTROL and only enable
>>>> + * clock with no divider value programmed.
>>>> + */
>>>> + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> + clk |= SDHCI_CLOCK_INT_EN;
>>>> + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>> +
>>>> + /* Wait max 20 ms */
>>>> + timeout = 20;
>>>> + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>>>> + & SDHCI_CLOCK_INT_STABLE)) {
>>>> + if (timeout == 0) {
>>>> + pr_err("%s: Internal clock never stabilised\n",
>>>> + mmc_hostname(host->mmc));
>>>> + return;
>>>> + }
>>>> + timeout--;
>>>> + mdelay(1);
>>>> + }
>>>> +
>>>> + clk |= SDHCI_CLOCK_CARD_EN;
>>>> + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>>>
>>> This is almost a copy/paste of sdhci_set_clock(). Can we make
>>> sdhci_set_clock() call a __sdhci_set_clock() function that takes
>>> unsigned int clock, and also a flag indicating if we want to set
>>> the internal clock divider or not? Then we can call
>>> __sdhci_set_clock() from sdhci_set_clock() with (clock, true) as
>>> arguments and (clock, false).
> Actually what you may be referring here is some sort of quirks which is not
> entertained any more for sdhci driver.
> sdhci is tending towards becoming a library and hence such changes are
> restricted.
>
> But I think we may do below changes to avoid duplication of code which
> enables the sdhci internal clock and waits for internal clock to be stable.
>
> Adrian, could you please tell if this should be ok?
That seems fine, but the name seems too long - how about changing
sdhci_set_clock_enable to sdhci_enable_clk.
> Then we may be able to call for sdhci_set_clock_enable function from
> sdhci_msm_set_clock.
>
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 42ef3eb..28e605c 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1343,19 +1343,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned
> int clock,
> }
> EXPORT_SYMBOL_GPL(sdhci_calc_clk);
>
> -void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk)
> {
> - u16 clk;
> - unsigned long timeout;
> -
> - host->mmc->actual_clock = 0;
> -
> - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> -
> - if (clock == 0)
> - return;
> -
> - clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
>
> clk |= SDHCI_CLOCK_INT_EN;
> sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> @@ -1377,6 +1366,24 @@ void sdhci_set_clock(struct sdhci_host *host,
> unsigned int clock)
> clk |= SDHCI_CLOCK_CARD_EN;
> sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> }
> +EXPORT_SYMBOL_GPL(sdhci_set_clock_enable);
> +
> +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> + u16 clk;
> + unsigned long timeout;
> +
> + host->mmc->actual_clock = 0;
> +
> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> + if (clock == 0)
> + return;
> +
> + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> +
> + sdhci_set_clock_enable(host, clk);
> +}
> EXPORT_SYMBOL_GPL(sdhci_set_clock);
>
> static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 766df17..43382e1 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -681,6 +681,7 @@ static inline bool sdhci_sdio_irq_enabled(struct
> sdhci_host *host)
> u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
> unsigned int *actual_clock);
> void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
> +void sdhci_set_clock_enable(struct sdhci_host *host, unsigned short clk);
> void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
> unsigned short vdd);
> void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
>
>
>
>> Adrian,
>> Could you please comment here ?
>>
>>>
>>>> +}
>>>> +
>>>> +/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
>>>> +static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned
>>>> int clock)
>>>> +{
>>>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>> + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>>>> + int rc;
>>>> +
>>>> + if (!clock) {
>>>> + msm_host->clk_rate = clock;
>>>> + goto out;
>>>> + }
>>>> +
>>>> + spin_unlock_irq(&host->lock);
>>>> + if (clock != msm_host->clk_rate) {
>>>
>>> Why do we need to check here? Can't we call clk_set_rate()
>>> Unconditionally?
>> Since it may so happen that above layers may call for ->set_clock
>> function with same requested clock more than once, hence we cache the
>> host->clock here.
>> Also, since requested clock (host->clock) can be say 400Mhz but the
>> actual pltfm supported clock would be say 384MHz.
>>
>>
>>>
>>>> + rc = clk_set_rate(msm_host->clk, clock);
>>>> + if (rc) {
>>>> + pr_err("%s: Failed to set clock at rate %u\n",
>>>> + mmc_hostname(host->mmc), clock);
>>>> + spin_lock_irq(&host->lock);
>>>> + goto out;
>>>
>>> Or replace the above two lines with goto err;
>> Ok, I will have another label out_lock instead of err.
>>>
>>>> + }
>>>> + msm_host->clk_rate = clock;
>>>> + pr_debug("%s: Setting clock at rate %lu\n",
>>>> + mmc_hostname(host->mmc), clk_get_rate(msm_host->clk));
>>>> + }
>>>
>>> And put an err label here.
>> will put the label here as out_lock;
>>>
>>>> + spin_lock_irq(&host->lock);
>>>> +out:
>>>> + __sdhci_msm_set_clock(host, clock);
>>>> +}
>>>> +
>>>> static const struct of_device_id sdhci_msm_dt_match[] = {
>>>> { .compatible = "qcom,sdhci-msm-v4" },
>>>> {},
>>>
>>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox