* Re: [PATCH V4 3/6] dt/bindings: Add bindings for Tegra GMI controller
From: Thierry Reding @ 2016-11-07 11:35 UTC (permalink / raw)
To: Mirza Krak
Cc: swarren-3lzwWm7+Weoh9ZMKESR00Q, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
gnurou-Re5JQEeQqe8AvxtiuMwx3w, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
pdeschrijver-DDmLM1+adcrQT0dZR+AlfA,
pgaikwad-DDmLM1+adcrQT0dZR+AlfA,
mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478507405-13204-4-git-send-email-mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1067 bytes --]
On Mon, Nov 07, 2016 at 09:30:02AM +0100, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> Document the devicetree bindings for the Generic Memory Interface (GMI)
> bus driver found on Tegra SOCs.
>
> Signed-off-by: Mirza Krak <mirza.krak-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Tested-by: Marcel Ziswiler <marcel.ziswiler-2KBjVHiyJgBBDgjK7y7TUQ@public.gmane.org>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>
> Changes in v2:
> - Updated examples and some information based on comments from Jon Hunter.
>
> Changes in v3:
> - Updates ranges description based on comments from Rob Herring
>
> Changes in v4:
> - renamed snor-*-inv to snor-*-active-high
>
> .../devicetree/bindings/bus/nvidia,tegra20-gmi.txt | 132 +++++++++++++++++++++
> 1 file changed, 132 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/bus/nvidia,tegra20-gmi.txt
Applied, thanks.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH/RESEND V4 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Mark Rutland @ 2016-11-07 11:34 UTC (permalink / raw)
To: zhichang.yuan
Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, arnd,
linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
kantyzc, xuwei5, marc.zyngier
In-Reply-To: <1478006926-240933-4-git-send-email-yuanzhichang@hisilicon.com>
Hi,
I received an off-list v5 of this for some reason.
I have several concerns with this, but given there's evidently a v5, I
intend to wait until that is posted before I reply with my comments.
Thanks,
Mark.
On Tue, Nov 01, 2016 at 09:28:46PM +0800, zhichang.yuan wrote:
> On Hip06, the accesses to LPC peripherals work in an indirect way. A
> corresponding LPC driver configure some registers in LPC master at first, then
> the real accesses on LPC slave devices are finished by the LPC master, which
> is transparent to LPC driver.
> This patch implement the relevant driver for Hip06 LPC. Cooperating with
> indirect-IO, ipmi messages is in service without any changes on ipmi driver.
>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
> .../arm/hisilicon/hisilicon-low-pin-count.txt | 31 ++
> MAINTAINERS | 8 +
> drivers/bus/Kconfig | 8 +
> drivers/bus/Makefile | 1 +
> drivers/bus/hisi_lpc.c | 501 +++++++++++++++++++++
> 5 files changed, 549 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> create mode 100644 drivers/bus/hisi_lpc.c
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..e681419
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> + Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> + locate on LPC bus can be accessed direclty. But some SoCs have independent
> + LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> + Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set for this device is mapped.
> +
> +Note:
> + The node name before '@' must be "isa" to represent the binding stick to the
> + ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> + compatible = "hisilicom,low-pin-count";
> + #address-cells = <2>;
> + #size-cells = <1>;
> + reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> + ipmi0: bt@e4 {
> + compatible = "ipmi-bt";
> + device_type = "ipmi";
> + reg = <0x01 0xe4 0x04>;
> + status = "disabled";
> + };
> +};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1cd38a7..7c69410 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5716,6 +5716,14 @@ F: include/uapi/linux/if_hippi.h
> F: net/802/hippi.c
> F: drivers/net/hippi/
>
> +HISILICON LPC BUS DRIVER
> +M: Zhichang Yuan <yuanzhichang@hisilicon.com>
> +L: linux-arm-kernel@lists.infradead.org
> +W: http://www.hisilicon.com
> +S: Maintained
> +F: drivers/bus/hisi_lpc.c
> +F: Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> +
> HISILICON NETWORK SUBSYSTEM DRIVER
> M: Yisen Zhuang <yisen.zhuang@huawei.com>
> M: Salil Mehta <salil.mehta@huawei.com>
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index 7010dca..a108abc 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
> arbiter. This driver provides timeout and target abort error handling
> and internal bus master decoding.
>
> +config HISILICON_LPC
> + bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
> + depends on (ARCH_HISI || COMPILE_TEST) && ARM64
> + select ARM64_INDIRECT_PIO
> + help
> + Driver needed for some legacy ISA devices attached to Low-Pin-Count
> + on Hisilicon Hip0X SoC.
> +
> config IMX_WEIM
> bool "Freescale EIM DRIVER"
> depends on ARCH_MXC
> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
> index c6cfa6b..10b4983 100644
> --- a/drivers/bus/Makefile
> +++ b/drivers/bus/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
> obj-$(CONFIG_ARM_CCN) += arm-ccn.o
>
> obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
> +obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o
> obj-$(CONFIG_IMX_WEIM) += imx-weim.o
> obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
> obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
> diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
> new file mode 100644
> index 0000000..9f48a1a
> --- /dev/null
> +++ b/drivers/bus/hisi_lpc.c
> @@ -0,0 +1,501 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + * Author: Zou Rongrong <zourongrong@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * 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/acpi.h>
> +#include <linux/console.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/serial_8250.h>
> +#include <linux/slab.h>
> +
> +/*
> + * this bit set means each IO operation will target to different port address;
> + * 0 means repeatly IO operations will be sticked on the same port, such as BT;
> + */
> +#define FG_INCRADDR_LPC 0x02
> +
> +struct lpc_cycle_para {
> + unsigned int opflags;
> + unsigned int csize;/* the data length of each operation */
> +};
> +
> +struct hisilpc_dev {
> + spinlock_t cycle_lock;
> + void __iomem *membase;
> + struct extio_ops io_ops;
> +};
> +
> +
> +/* The maximum continous operations*/
> +#define LPC_MAX_OPCNT 16
> +/* only support IO data unit length is four at maximum */
> +#define LPC_MAX_DULEN 4
> +#if LPC_MAX_DULEN > LPC_MAX_OPCNT
> +#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
> +#endif
> +
> +#define LPC_REG_START 0x00/* start a new LPC cycle */
> +#define LPC_REG_OP_STATUS 0x04/* the current LPC status */
> +#define LPC_REG_IRQ_ST 0x08/* interrupt enable&status */
> +#define LPC_REG_OP_LEN 0x10/* how many LPC cycles each start */
> +#define LPC_REG_CMD 0x14/* command for the required LPC cycle */
> +#define LPC_REG_ADDR 0x20/* LPC target address */
> +#define LPC_REG_WDATA 0x24/* data to be written */
> +#define LPC_REG_RDATA 0x28/* data coming from peer */
> +
> +
> +/* The command register fields*/
> +#define LPC_CMD_SAMEADDR 0x08
> +#define LPC_CMD_TYPE_IO 0x00
> +#define LPC_CMD_WRITE 0x01
> +#define LPC_CMD_READ 0x00
> +/* the bit attribute is W1C. 1 represents OK. */
> +#define LPC_STAT_BYIRQ 0x02
> +
> +#define LPC_STATUS_IDLE 0x01
> +#define LPC_OP_FINISHED 0x02
> +
> +#define START_WORK 0x01
> +
> +/*
> + * The minimal waiting interval... Suggest it is not less than 10.
> + * Bigger value probably will lower the performance.
> + */
> +#define LPC_NSEC_PERWAIT 100
> +/*
> + * The maximum waiting time is about 128us.
> + * The fastest IO cycle time is about 390ns, but the worst case will wait
> + * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
> + * burst cycles is 16. So, the maximum waiting time is about 128us under
> + * worst case.
> + * choose 1300 as the maximum.
> + */
> +#define LPC_MAX_WAITCNT 1300
> +/* About 10us. This is specfic for single IO operation, such as inb. */
> +#define LPC_PEROP_WAITCNT 100
> +
> +
> +static inline int wait_lpc_idle(unsigned char *mbase,
> + unsigned int waitcnt) {
> + u32 opstatus;
> +
> + while (waitcnt--) {
> + ndelay(LPC_NSEC_PERWAIT);
> + opstatus = readl(mbase + LPC_REG_OP_STATUS);
> + if (opstatus & LPC_STATUS_IDLE)
> + return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
> + }
> + return -ETIME;
> +}
> +
> +
> +/**
> + * hisilpc_target_in - trigger a series of lpc cycles to read required data
> + * from target periperal.
> + * @pdev: pointer to hisi lpc device
> + * @para: some paramerters used to control the lpc I/O operations
> + * @ptaddr: the lpc I/O target port address
> + * @buf: where the read back data is stored
> + * @opcnt: how many I/O operations required in this calling
> + *
> + * only one byte data is read each I/O operation.
> + *
> + * Returns 0 on success, non-zero on fail.
> + *
> + */
> +static int hisilpc_target_in(struct hisilpc_dev *pdev,
> + struct lpc_cycle_para *para,
> + unsigned long ptaddr, unsigned char *buf,
> + unsigned long opcnt)
> +{
> + unsigned int cmd_word;
> + unsigned int waitcnt;
> + int retval;
> + unsigned long flags;
> + unsigned long cnt_per_trans;
> +
> + if (!buf || !opcnt || !para || !para->csize || !pdev)
> + return -EINVAL;
> +
> + if (opcnt > LPC_MAX_OPCNT)
> + return -EINVAL;
> +
> + cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
> + waitcnt = (LPC_PEROP_WAITCNT);
> + if (!(para->opflags & FG_INCRADDR_LPC)) {
> + cmd_word |= LPC_CMD_SAMEADDR;
> + waitcnt = LPC_MAX_WAITCNT;
> + }
> +
> + retval = 0;
> + cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
> + for (; opcnt && !retval; cnt_per_trans = para->csize) {
> + /* whole operation must be atomic */
> + spin_lock_irqsave(&pdev->cycle_lock, flags);
> +
> + writel(cnt_per_trans, pdev->membase + LPC_REG_OP_LEN);
> +
> + writel(cmd_word, pdev->membase + LPC_REG_CMD);
> +
> + writel(ptaddr, pdev->membase + LPC_REG_ADDR);
> +
> + writel(START_WORK, pdev->membase + LPC_REG_START);
> +
> + /* whether the operation is finished */
> + retval = wait_lpc_idle(pdev->membase, waitcnt);
> + if (!retval) {
> + opcnt -= cnt_per_trans;
> + for (; cnt_per_trans--; buf++)
> + *buf = readl(pdev->membase + LPC_REG_RDATA);
> + }
> +
> + spin_unlock_irqrestore(&pdev->cycle_lock, flags);
> + }
> +
> + return retval;
> +}
> +
> +/**
> + * hisilpc_target_out - trigger a series of lpc cycles to write required data
> + * to target periperal.
> + * @pdev: pointer to hisi lpc device
> + * @para: some paramerters used to control the lpc I/O operations
> + * @ptaddr: the lpc I/O target port address
> + * @buf: where the data to be written is stored
> + * @opcnt: how many I/O operations required
> + *
> + * only one byte data is read each I/O operation.
> + *
> + * Returns 0 on success, non-zero on fail.
> + *
> + */
> +static int hisilpc_target_out(struct hisilpc_dev *pdev,
> + struct lpc_cycle_para *para,
> + unsigned long ptaddr,
> + const unsigned char *buf,
> + unsigned long opcnt)
> +{
> + unsigned int cmd_word;
> + unsigned int waitcnt;
> + int retval;
> + unsigned long flags;
> + unsigned long cnt_per_trans;
> +
> + if (!buf || !opcnt || !para || !pdev)
> + return -EINVAL;
> +
> + if (opcnt > LPC_MAX_OPCNT)
> + return -EINVAL;
> + /* default is increasing address */
> + cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
> + waitcnt = (LPC_PEROP_WAITCNT);
> + if (!(para->opflags & FG_INCRADDR_LPC)) {
> + cmd_word |= LPC_CMD_SAMEADDR;
> + waitcnt = LPC_MAX_WAITCNT;
> + }
> +
> + retval = 0;
> + cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
> + for (; opcnt && !retval; cnt_per_trans = para->csize) {
> + spin_lock_irqsave(&pdev->cycle_lock, flags);
> +
> + writel(cnt_per_trans, pdev->membase + LPC_REG_OP_LEN);
> + opcnt -= cnt_per_trans;
> + for (; cnt_per_trans--; buf++)
> + writel(*buf, pdev->membase + LPC_REG_WDATA);
> +
> + writel(cmd_word, pdev->membase + LPC_REG_CMD);
> +
> + writel(ptaddr, pdev->membase + LPC_REG_ADDR);
> +
> + writel(START_WORK, pdev->membase + LPC_REG_START);
> +
> + /* whether the operation is finished */
> + retval = wait_lpc_idle(pdev->membase, waitcnt);
> +
> + spin_unlock_irqrestore(&pdev->cycle_lock, flags);
> + }
> +
> + return retval;
> +}
> +
> +
> +/**
> + * hisilpc_comm_in - read/input the data from the I/O peripheral through LPC.
> + * @devobj: pointer to the device information relevant to LPC controller.
> + * @ptaddr: the target I/O port address.
> + * @dlen: the data length required to read from the target I/O port.
> + *
> + * when succeed, the data read back is stored in buffer pointed by inbuf.
> + * For inb, return the data read from I/O or -1 when error occur.
> + */
> +static u64 hisilpc_comm_in(void *devobj, unsigned long ptaddr, size_t dlen)
> +{
> + struct hisilpc_dev *lpcdev;
> + struct lpc_cycle_para iopara;
> + u32 rd_data;
> + unsigned char *newbuf;
> + int ret = 0;
> +
> + if (!devobj || !dlen || dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
> + return -1;
> +
> + /* the local buffer must be enough for one data unit */
> + if (sizeof(rd_data) < dlen)
> + return -1;
> +
> + newbuf = (unsigned char *)&rd_data;
> +
> + lpcdev = (struct hisilpc_dev *)devobj;
> +
> + iopara.opflags = FG_INCRADDR_LPC;
> + iopara.csize = dlen;
> +
> + ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
> + if (ret)
> + return -1;
> +
> + return le32_to_cpu(rd_data);
> +}
> +
> +/**
> + * hisilpc_comm_out - write/output the data whose maximal length is four bytes to
> + * the I/O peripheral through LPC.
> + * @devobj: pointer to the device information relevant to LPC controller.
> + * @outval: a value to be outputed from caller, maximum is four bytes.
> + * @ptaddr: the target I/O port address.
> + * @dlen: the data length required writing to the target I/O port .
> + *
> + * This function is corresponding to out(b,w,l) only
> + *
> + */
> +static void hisilpc_comm_out(void *devobj, unsigned long ptaddr,
> + u32 outval, size_t dlen)
> +{
> + struct hisilpc_dev *lpcdev;
> + struct lpc_cycle_para iopara;
> + const unsigned char *newbuf;
> +
> + if (!devobj || !dlen || dlen > LPC_MAX_DULEN)
> + return;
> +
> + if (sizeof(outval) < dlen)
> + return;
> +
> + outval = cpu_to_le32(outval);
> +
> + newbuf = (const unsigned char *)&outval;
> + lpcdev = (struct hisilpc_dev *)devobj;
> +
> + iopara.opflags = FG_INCRADDR_LPC;
> + iopara.csize = dlen;
> +
> + hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
> +}
> +
> +
> +/**
> + * hisilpc_comm_ins - read/input the data in buffer to the I/O peripheral
> + * through LPC, it corresponds to ins(b,w,l)
> + * @devobj: pointer to the device information relevant to LPC controller.
> + * @ptaddr: the target I/O port address.
> + * @inbuf: a buffer where read/input data bytes are stored.
> + * @dlen: the data length required writing to the target I/O port .
> + * @count: how many data units whose length is dlen will be read.
> + *
> + */
> +static u64 hisilpc_comm_ins(void *devobj, unsigned long ptaddr,
> + void *inbuf, size_t dlen, unsigned int count)
> +{
> + struct hisilpc_dev *lpcdev;
> + struct lpc_cycle_para iopara;
> + unsigned char *newbuf;
> + unsigned int loopcnt, cntleft;
> + unsigned int max_perburst;
> + int ret = 0;
> +
> + if (!devobj || !inbuf || !count || !dlen ||
> + dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
> + return -1;
> +
> + iopara.opflags = 0;
> + if (dlen > 1)
> + iopara.opflags |= FG_INCRADDR_LPC;
> + iopara.csize = dlen;
> +
> + lpcdev = (struct hisilpc_dev *)devobj;
> + newbuf = (unsigned char *)inbuf;
> + /*
> + * ensure data stream whose lenght is multiple of dlen to be processed
> + * each IO input
> + */
> + max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
> + cntleft = count * dlen;
> + do {
> + loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
> + ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf,
> + loopcnt);
> + if (ret)
> + break;
> + newbuf += loopcnt;
> + cntleft -= loopcnt;
> + } while (cntleft);
> +
> + return ret;
> +}
> +
> +/**
> + * hisilpc_comm_outs - write/output the data in buffer to the I/O peripheral
> + * through LPC, it corresponds to outs(b,w,l)
> + * @devobj: pointer to the device information relevant to LPC controller.
> + * @ptaddr: the target I/O port address.
> + * @outbuf: a buffer where write/output data bytes are stored.
> + * @dlen: the data length required writing to the target I/O port .
> + * @count: how many data units whose length is dlen will be written.
> + *
> + */
> +static void hisilpc_comm_outs(void *devobj, unsigned long ptaddr,
> + const void *outbuf, size_t dlen, unsigned int count)
> +{
> + struct hisilpc_dev *lpcdev;
> + struct lpc_cycle_para iopara;
> + const unsigned char *newbuf;
> + unsigned int loopcnt, cntleft;
> + unsigned int max_perburst;
> + int ret = 0;
> +
> + if (!devobj || !outbuf || !count || !dlen ||
> + dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
> + return;
> +
> + iopara.opflags = 0;
> + if (dlen > 1)
> + iopara.opflags |= FG_INCRADDR_LPC;
> + iopara.csize = dlen;
> +
> + lpcdev = (struct hisilpc_dev *)devobj;
> + newbuf = (unsigned char *)outbuf;
> + /*
> + * ensure data stream whose lenght is multiple of dlen to be processed
> + * each IO input
> + */
> + max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
> + cntleft = count * dlen;
> + do {
> + loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
> + ret = hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
> + loopcnt);
> + if (ret)
> + break;
> + newbuf += loopcnt;
> + cntleft -= loopcnt;
> + } while (cntleft);
> +}
> +
> +
> +/**
> + * hisilpc_probe - the probe callback function for hisi lpc device,
> + * will finish all the intialization.
> + * @pdev: the platform device corresponding to hisi lpc
> + *
> + * Returns 0 on success, non-zero on fail.
> + *
> + */
> +static int hisilpc_probe(struct platform_device *pdev)
> +{
> + struct resource *iores;
> + struct hisilpc_dev *lpcdev;
> + int ret;
> +
> + dev_info(&pdev->dev, "hslpc start probing...\n");
> +
> + lpcdev = devm_kzalloc(&pdev->dev,
> + sizeof(struct hisilpc_dev), GFP_KERNEL);
> + if (!lpcdev)
> + return -ENOMEM;
> +
> + spin_lock_init(&lpcdev->cycle_lock);
> + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
> + if (IS_ERR(lpcdev->membase)) {
> + dev_err(&pdev->dev, "No mem resource for memory mapping!\n");
> + return PTR_ERR(lpcdev->membase);
> + }
> + /*
> + * The first PCIBIOS_MIN_IO is reserved specific for indirectIO.
> + * It will separate indirectIO range from pci host bridge to
> + * avoid the possible PIO conflict.
> + * Set the indirectIO range directly here.
> + */
> + lpcdev->io_ops.start = 0;
> + lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> + lpcdev->io_ops.devpara = lpcdev;
> + lpcdev->io_ops.pfin = hisilpc_comm_in;
> + lpcdev->io_ops.pfout = hisilpc_comm_out;
> + lpcdev->io_ops.pfins = hisilpc_comm_ins;
> + lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> +
> + platform_set_drvdata(pdev, lpcdev);
> +
> + arm64_set_extops(&lpcdev->io_ops);
> +
> + /*
> + * The children scanning is only for dts mode. For ACPI children,
> + * the corresponding devices had be created during acpi scanning.
> + */
> + ret = 0;
> + if (!has_acpi_companion(&pdev->dev))
> + ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +
> + if (!ret)
> + dev_info(&pdev->dev, "hslpc end probing. range[0x%lx - %lx]\n",
> + arm64_extio_ops->start, arm64_extio_ops->end);
> + else
> + dev_info(&pdev->dev, "hslpc probing is fail(%d)\n", ret);
> +
> + return ret;
> +}
> +
> +static const struct of_device_id hisilpc_of_match[] = {
> + {
> + .compatible = "hisilicon,low-pin-count",
> + },
> + {},
> +};
> +
> +static const struct acpi_device_id hisilpc_acpi_match[] = {
> + {"HISI0191", },
> + {},
> +};
> +
> +static struct platform_driver hisilpc_driver = {
> + .driver = {
> + .name = "hisi_lpc",
> + .of_match_table = hisilpc_of_match,
> + .acpi_match_table = hisilpc_acpi_match,
> + },
> + .probe = hisilpc_probe,
> +};
> +
> +
> +builtin_platform_driver(hisilpc_driver);
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" 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: [PATCH V4 2/6] clk: tegra: add TEGRA30_CLK_NOR to init table
From: Thierry Reding @ 2016-11-07 11:28 UTC (permalink / raw)
To: Mirza Krak
Cc: swarren, jonathanh, gnurou, linux, pdeschrijver, pgaikwad,
mturquette, sboyd, robh+dt, mark.rutland, devicetree, linux-tegra,
linux-kernel, linux-arm-kernel, linux-clk
In-Reply-To: <1478507405-13204-3-git-send-email-mirza.krak@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 807 bytes --]
On Mon, Nov 07, 2016 at 09:30:01AM +0100, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add TEGRA30_CLK_NOR to init table and set default rate to 127 MHz which
> is max rate.
>
> The maximum rate value of 127 MHz is pulled from the downstream L4T
> kernel.
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> Acked-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>
> Changes in v2:
> - no changes
>
> Changes in v3:
> - Added comment in commit message where I got the maximum rates from.
>
> Changes in V4:
> - no changes
>
> drivers/clk/tegra/clk-tegra30.c | 1 +
> 1 file changed, 1 insertion(+)
Applied, thanks.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH V4 1/6] clk: tegra: add TEGRA20_CLK_NOR to init table
From: Thierry Reding @ 2016-11-07 11:27 UTC (permalink / raw)
To: Mirza Krak
Cc: mark.rutland, gnurou, pgaikwad, linux-clk, swarren, linux-kernel,
pdeschrijver, sboyd, linux, jonathanh, devicetree, robh+dt,
linux-tegra, mturquette, linux-arm-kernel
In-Reply-To: <1478507405-13204-2-git-send-email-mirza.krak@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 724 bytes --]
On Mon, Nov 07, 2016 at 09:30:00AM +0100, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add TEGRA20_CLK_NOR to init table and set default rate to 92 MHz which
> is max rate.
>
> The maximum rate value of 92 MHz is pulled from the downstream L4T
> kernel.
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> Acked-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>
> Changes in v2:
> - no changes
>
> Changes in v3:
> - Added comment in commit message where I got the maximum rates from.
>
> Changes in V4:
> - no changes
Applied, thanks.
Thierry
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v6 14/14] sdhci: sdhci-msm: update dll configuration
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani, Krishna Konda
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
The newer msm sdhci's cores use a different DLL hardware for HS400.
Update the configuration and calibration of the newer DLL block.
The HS400 DLL block used previously is CDC LP 533 and requires
programming multiple registers and waiting for configuration to
complete and then enable it. It has about 18 register writes and
two register reads.
The newer HS400 DLL block is SDC4 DLL and requires two register
writes for configuration and one register read to confirm that it
is initialized. There is an additional register write to enable
the power save mode for SDC4 DLL block.
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
Signed-off-by: Krishna Konda <kkonda@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 132 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 130 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index ae19d1a..84812e6 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -51,6 +51,7 @@
#define INT_MASK 0xf
#define MAX_PHASES 16
#define CORE_DLL_LOCK BIT(7)
+#define CORE_DDR_DLL_LOCK BIT(11)
#define CORE_DLL_EN BIT(16)
#define CORE_CDR_EN BIT(17)
#define CORE_CK_OUT_EN BIT(18)
@@ -62,6 +63,7 @@
#define CORE_DLL_STATUS 0x108
#define CORE_DLL_CONFIG_2 0x1b4
+#define CORE_DDR_CAL_EN BIT(0)
#define CORE_FLL_CYCLE_CNT BIT(18)
#define CORE_DLL_CLOCK_DISABLE BIT(21)
@@ -100,6 +102,11 @@
#define CORE_DDR_200_CFG 0x184
#define CORE_CDC_T4_DLY_SEL BIT(0)
#define CORE_START_CDC_TRAFFIC BIT(6)
+#define CORE_VENDOR_SPEC3 0x1b0
+#define CORE_PWRSAVE_DLL BIT(3)
+
+#define CORE_DDR_CONFIG 0x1b8
+#define DDR_CONFIG_POR_VAL 0x80040853
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
@@ -126,6 +133,7 @@ struct sdhci_msm_host {
bool tuning_done;
bool calibration_done;
u8 saved_tuning_phase;
+ bool use_cdclp533;
};
/* Platform specific tuning */
@@ -583,6 +591,93 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
return ret;
}
+static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
+{
+ u32 dll_status, config;
+ int ret;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Currently the CORE_DDR_CONFIG register defaults to desired
+ * configuration on reset. Currently reprogramming the power on
+ * reset (POR) value in case it might have been modified by
+ * bootloaders. In the future, if this changes, then the desired
+ * values will need to be programmed appropriately.
+ */
+ writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
+
+ /* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config |= CORE_DDR_CAL_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+
+ /* Poll on DDR_DLL_LOCK bit in CORE_DLL_STATUS to be set */
+ ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
+ dll_status,
+ (dll_status & CORE_DDR_DLL_LOCK),
+ 10, 1000);
+
+ if (ret == -ETIMEDOUT) {
+ pr_err("%s: %s: CM_DLL_SDC4 calibration was not completed\n",
+ mmc_hostname(host->mmc), __func__);
+ goto out;
+ }
+
+ /* set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3 */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3);
+ config |= CORE_PWRSAVE_DLL;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC3);
+
+ /*
+ * Drain writebuffer to ensure above DLL calibration
+ * and PWRSAVE DLL is enabled.
+ */
+ wmb();
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
+static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+ u32 config;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Retuning in HS400 (DDR mode) will fail, just reset the
+ * tuning block and restore the saved tuning phase.
+ */
+ ret = msm_init_cm_dll(host);
+ if (ret)
+ goto out;
+
+ /* Set the selected phase in delay line hw block */
+ ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+ if (ret)
+ goto out;
+
+ /* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CMD_DAT_TRACK_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ if (msm_host->use_cdclp533)
+ /* Calibrate CDCLP533 DLL HW */
+ ret = sdhci_msm_cdclp533_calibration(host);
+ else
+ /* Calibrate CM_DLL_SDC4 HW */
+ ret = sdhci_msm_cm_dll_sdc4_calibration(host);
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
int tuning_seq_cnt = 3;
@@ -731,7 +826,7 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
if (host->clock > CORE_FREQ_100MHZ &&
msm_host->tuning_done && !msm_host->calibration_done &&
(mmc->ios.timing == MMC_TIMING_MMC_HS400))
- if (!sdhci_msm_cdclp533_calibration(host))
+ if (!sdhci_msm_hs400_dll_calibration(host))
msm_host->calibration_done = true;
spin_lock_irq(&host->lock);
}
@@ -842,7 +937,7 @@ 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);
struct mmc_ios curr_ios = host->mmc->ios;
- u32 config;
+ u32 config, dll_lock;
int rc;
if (!clock) {
@@ -899,7 +994,33 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
config |= CORE_HC_SELECT_IN_EN;
writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
}
+ if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
+ /*
+ * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
+ * CORE_DLL_STATUS to be set. This should get set
+ * within 15 us at 200 MHz.
+ */
+ rc = readl_relaxed_poll_timeout(host->ioaddr +
+ CORE_DLL_STATUS,
+ dll_lock,
+ (dll_lock &
+ (CORE_DLL_LOCK |
+ CORE_DDR_DLL_LOCK)), 10,
+ 1000);
+ if (rc == -ETIMEDOUT)
+ pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
+ mmc_hostname(host->mmc), dll_lock);
+ }
} else {
+ if (!msm_host->use_cdclp533) {
+ /* set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3 */
+ config = readl_relaxed(host->ioaddr +
+ CORE_VENDOR_SPEC3);
+ config &= ~CORE_PWRSAVE_DLL;
+ writel_relaxed(config, host->ioaddr +
+ CORE_VENDOR_SPEC3);
+ }
+
/* Select the default clock (free running MCLK) */
config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
config &= ~CORE_HC_MCLK_SEL_MASK;
@@ -1086,6 +1207,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->use_14lpp_dll_reset = true;
/*
+ * SDCC 5 controller with major version 1, minor version 0x34 and later
+ * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL.
+ */
+ if ((core_major == 1) && (core_minor < 0x34))
+ msm_host->use_cdclp533 = true;
+
+ /*
* Support for some capabilities is not advertised by newer
* controller versions and must be explicitly enabled.
*/
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 13/14] mmc: sdhci-msm: Add calibration tuning for CDCLP533 circuit
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
In HS400 mode a new RCLK is introduced on the interface for read data
transfers. The eMMC5.0 device transmits the read data to the host with
respect to rising and falling edges of RCLK. In order to ensure correct
operation of read data transfers in HS400 mode, the incoming RX data
needs to be sampled by delayed version of RCLK.
The CDCLP533 delay circuit shifts the RCLK by T/4. It needs to be
initialized, configured and enabled once during HS400 mode switch and
when operational voltage/clock is changed.
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 163 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 6431bb8..ae19d1a 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
#include <linux/slab.h>
+#include <linux/iopoll.h>
#include "sdhci-pltfm.h"
@@ -57,6 +58,7 @@
#define CORE_DLL_PDN BIT(29)
#define CORE_DLL_RST BIT(30)
#define CORE_DLL_CONFIG 0x100
+#define CORE_CMD_DAT_TRACK_SEL BIT(0)
#define CORE_DLL_STATUS 0x108
#define CORE_DLL_CONFIG_2 0x1b4
@@ -72,6 +74,33 @@
#define CORE_HC_SELECT_IN_HS400 (6 << 19)
#define CORE_HC_SELECT_IN_MASK (7 << 19)
+#define CORE_CSR_CDC_CTLR_CFG0 0x130
+#define CORE_SW_TRIG_FULL_CALIB BIT(16)
+#define CORE_HW_AUTOCAL_ENA BIT(17)
+
+#define CORE_CSR_CDC_CTLR_CFG1 0x134
+#define CORE_CSR_CDC_CAL_TIMER_CFG0 0x138
+#define CORE_TIMER_ENA BIT(16)
+
+#define CORE_CSR_CDC_CAL_TIMER_CFG1 0x13C
+#define CORE_CSR_CDC_REFCOUNT_CFG 0x140
+#define CORE_CSR_CDC_COARSE_CAL_CFG 0x144
+#define CORE_CDC_OFFSET_CFG 0x14C
+#define CORE_CSR_CDC_DELAY_CFG 0x150
+#define CORE_CDC_SLAVE_DDA_CFG 0x160
+#define CORE_CSR_CDC_STATUS0 0x164
+#define CORE_CALIBRATION_DONE BIT(0)
+
+#define CORE_CDC_ERROR_CODE_MASK 0x7000000
+
+#define CORE_CSR_CDC_GEN_CFG 0x178
+#define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
+#define CORE_CDC_SWITCH_RC_EN BIT(1)
+
+#define CORE_DDR_200_CFG 0x184
+#define CORE_CDC_T4_DLY_SEL BIT(0)
+#define CORE_START_CDC_TRAFFIC BIT(6)
+
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
#define INVALID_TUNING_PHASE -1
@@ -429,6 +458,131 @@ static int msm_init_cm_dll(struct sdhci_host *host)
return 0;
}
+static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ u32 config, calib_done;
+ int ret;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Retuning in HS400 (DDR mode) will fail, just reset the
+ * tuning block and restore the saved tuning phase.
+ */
+ ret = msm_init_cm_dll(host);
+ if (ret)
+ goto out;
+
+ /* Set the selected phase in delay line hw block */
+ ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+ if (ret)
+ goto out;
+
+ /* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CMD_DAT_TRACK_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ /* Write 0 to CDC_T4_DLY_SEL field in VENDOR_SPEC_DDR200_CFG */
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config &= ~CORE_CDC_T4_DLY_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+ /* Write 0 to CDC_SWITCH_BYPASS_OFF field in CORE_CSR_CDC_GEN_CFG */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+ config &= ~CORE_CDC_SWITCH_BYPASS_OFF;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ /* Write 1 to CDC_SWITCH_RC_EN field in CORE_CSR_CDC_GEN_CFG */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+ config |= CORE_CDC_SWITCH_RC_EN;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ /* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config &= ~CORE_START_CDC_TRAFFIC;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+ /*
+ * Perform CDC Register Initialization Sequence
+ *
+ * CORE_CSR_CDC_CTLR_CFG0 0x11800EC
+ * CORE_CSR_CDC_CTLR_CFG1 0x3011111
+ * CORE_CSR_CDC_CAL_TIMER_CFG0 0x1201000
+ * CORE_CSR_CDC_CAL_TIMER_CFG1 0x4
+ * CORE_CSR_CDC_REFCOUNT_CFG 0xCB732020
+ * CORE_CSR_CDC_COARSE_CAL_CFG 0xB19
+ * CORE_CSR_CDC_DELAY_CFG 0x3AC
+ * CORE_CDC_OFFSET_CFG 0x0
+ * CORE_CDC_SLAVE_DDA_CFG 0x16334
+ */
+
+ writel_relaxed(0x11800EC, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ writel_relaxed(0x3011111, host->ioaddr + CORE_CSR_CDC_CTLR_CFG1);
+ writel_relaxed(0x1201000, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+ writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
+ writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
+ writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
+ writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+ writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
+ writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
+
+ /* CDC HW Calibration */
+
+ /* Write 1 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config |= CORE_SW_TRIG_FULL_CALIB;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 0 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config &= ~CORE_SW_TRIG_FULL_CALIB;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 1 to HW_AUTOCAL_ENA field in CORE_CSR_CDC_CTLR_CFG0 */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config |= CORE_HW_AUTOCAL_ENA;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 1 to TIMER_ENA field in CORE_CSR_CDC_CAL_TIMER_CFG0 */
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+ config |= CORE_TIMER_ENA;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+
+ /* Poll on CALIBRATION_DONE field in CORE_CSR_CDC_STATUS0 to be 1 */
+ ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_CSR_CDC_STATUS0,
+ calib_done,
+ (calib_done & CORE_CALIBRATION_DONE),
+ 1, 50);
+
+ if (ret == -ETIMEDOUT) {
+ pr_err("%s: %s: CDC calibration was not completed\n",
+ mmc_hostname(host->mmc), __func__);
+ goto out;
+ }
+
+ /* Verify CDC_ERROR_CODE field in CORE_CSR_CDC_STATUS0 is 0 */
+ ret = readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
+ & CORE_CDC_ERROR_CODE_MASK;
+ if (ret) {
+ pr_err("%s: %s: CDC error code %d\n",
+ mmc_hostname(host->mmc), __func__, ret);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Write 1 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config |= CORE_START_CDC_TRAFFIC;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
int tuning_seq_cnt = 3;
@@ -571,6 +725,15 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+ spin_unlock_irq(&host->lock);
+ /* CDCLP533 HW calibration is only required for HS400 mode*/
+ if (host->clock > CORE_FREQ_100MHZ &&
+ msm_host->tuning_done && !msm_host->calibration_done &&
+ (mmc->ios.timing == MMC_TIMING_MMC_HS400))
+ if (!sdhci_msm_cdclp533_calibration(host))
+ msm_host->calibration_done = true;
+ spin_lock_irq(&host->lock);
}
static void sdhci_msm_voltage_switch(struct sdhci_host *host)
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 12/14] mmc: sdhci-msm: Save the calculated tuning phase
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
shawn.lin-TNX95d0MmH7DzftRWevZcw, sboyd-sgV2jX0FEOL9JmXXK+q4OQ
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
david.brown-QSEj5FYQhm4dnm+yROfE0A,
andy.gross-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
david.griego-QSEj5FYQhm4dnm+yROfE0A,
stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
pramod.gurav-QSEj5FYQhm4dnm+yROfE0A, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Save the tuning phase once the tuning is performed.
This phase value will be used while calibrating DLL
for HS400 mode.
Signed-off-by: Ritesh Harjani <riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/mmc/host/sdhci-msm.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2561c41..6431bb8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -74,6 +74,7 @@
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
+#define INVALID_TUNING_PHASE -1
#define TCXO_FREQ 19200000
#define SDHCI_MSM_MIN_CLOCK 400000
#define CORE_FREQ_100MHZ (100 * 1000 * 1000)
@@ -95,6 +96,7 @@ struct sdhci_msm_host {
bool use_14lpp_dll_reset;
bool tuning_done;
bool calibration_done;
+ u8 saved_tuning_phase;
};
/* Platform specific tuning */
@@ -134,6 +136,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
u32 config;
struct mmc_host *mmc = host->mmc;
+ if (phase > 0xf)
+ return -EINVAL;
+
spin_lock_irqsave(&host->lock, flags);
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
@@ -431,6 +436,8 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
int rc;
struct mmc_host *mmc = host->mmc;
struct mmc_ios ios = host->mmc->ios;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
/*
* Tuning is required for SDR104, HS200 and HS400 cards and
@@ -455,6 +462,7 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
if (rc)
return rc;
+ msm_host->saved_tuning_phase = phase;
rc = mmc_send_tuning(mmc, opcode, NULL);
if (!rc) {
/* Tuning is successful at this tuning point */
@@ -826,6 +834,8 @@ static int sdhci_msm_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
+ msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+
/* Setup SDCC bus voter clock. */
msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (!IS_ERR(msm_host->bus_clk)) {
--
The 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 related
* [PATCH v6 11/14] mmc: sdhci-msm: Add HS400 platform support
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
From: Venkat Gopalakrishnan <venkatg@codeaurora.org>
The following msm platform specific changes are added to support HS400.
- Allow tuning for HS400 mode.
- Configure HS400 timing mode using the VENDOR_SPECIFIC_FUNC register.
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 127 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 117 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 220567c..2561c41 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -31,6 +31,7 @@
#define HC_MODE_EN 0x1
#define CORE_POWER 0x0
#define CORE_SW_RST BIT(7)
+#define FF_CLK_SW_RST_DIS BIT(13)
#define CORE_PWRCTL_STATUS 0xdc
#define CORE_PWRCTL_MASK 0xe0
@@ -64,11 +65,18 @@
#define CORE_VENDOR_SPEC 0x10c
#define CORE_CLK_PWRSAVE BIT(1)
+#define CORE_HC_MCLK_SEL_DFLT (2 << 8)
+#define CORE_HC_MCLK_SEL_HS400 (3 << 8)
+#define CORE_HC_MCLK_SEL_MASK (3 << 8)
+#define CORE_HC_SELECT_IN_EN BIT(18)
+#define CORE_HC_SELECT_IN_HS400 (6 << 19)
+#define CORE_HC_SELECT_IN_MASK (7 << 19)
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
#define TCXO_FREQ 19200000
#define SDHCI_MSM_MIN_CLOCK 400000
+#define CORE_FREQ_100MHZ (100 * 1000 * 1000)
#define CDR_SELEXT_SHIFT 20
#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
@@ -85,6 +93,8 @@ struct sdhci_msm_host {
unsigned long clk_rate;
struct mmc_host *mmc;
bool use_14lpp_dll_reset;
+ bool tuning_done;
+ bool calibration_done;
};
/* Platform specific tuning */
@@ -173,8 +183,8 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
* Find out the greatest range of consecuitive selected
* DLL clock output phases that can be used as sampling
* setting for SD3.0 UHS-I card read operation (in SDR104
- * timing mode) or for eMMC4.5 card read operation (in HS200
- * timing mode).
+ * timing mode) or for eMMC4.5 card read operation (in
+ * HS400/HS200 timing mode).
* Select the 3/4 of the range and configure the DLL with the
* selected DLL clock output phase.
*/
@@ -426,9 +436,10 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
* Tuning is required for SDR104, HS200 and HS400 cards and
* if clock frequency is greater than 100MHz in these modes.
*/
- if (host->clock <= 100 * 1000 * 1000 ||
- !((ios.timing == MMC_TIMING_MMC_HS200) ||
- (ios.timing == MMC_TIMING_UHS_SDR104)))
+ if (host->clock <= CORE_FREQ_100MHZ ||
+ !(ios.timing == MMC_TIMING_MMC_HS400 ||
+ ios.timing == MMC_TIMING_MMC_HS200 ||
+ ios.timing == MMC_TIMING_UHS_SDR104))
return 0;
retry:
@@ -479,6 +490,8 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
rc = -EIO;
}
+ if (!rc)
+ msm_host->tuning_done = true;
return rc;
}
@@ -486,7 +499,10 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
unsigned int uhs)
{
struct mmc_host *mmc = host->mmc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u16 ctrl_2;
+ u32 config;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
@@ -501,6 +517,7 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
case MMC_TIMING_UHS_SDR50:
ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
break;
+ case MMC_TIMING_MMC_HS400:
case MMC_TIMING_MMC_HS200:
case MMC_TIMING_UHS_SDR104:
ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
@@ -517,11 +534,31 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
* provide feedback clock, the mode selection can be any value less
* than 3'b011 in bits [2:0] of HOST CONTROL2 register.
*/
- if (host->clock <= 100000000 &&
- (uhs == MMC_TIMING_MMC_HS400 ||
- uhs == MMC_TIMING_MMC_HS200 ||
- uhs == MMC_TIMING_UHS_SDR104))
- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ if (host->clock <= CORE_FREQ_100MHZ) {
+ if ((uhs == MMC_TIMING_MMC_HS400) ||
+ (uhs == MMC_TIMING_MMC_HS200) ||
+ (uhs == MMC_TIMING_UHS_SDR104))
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ /*
+ * Make sure DLL is disabled when not required
+ *
+ * Write 1 to DLL_RST bit of DLL_CONFIG register
+ */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ /* Write 1 to DLL_PDN bit of DLL_CONFIG register */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ /*
+ * The DLL needs to be restored and CDCLP533 recalibrated
+ * when the clock frequency is set back to 400MHz.
+ */
+ msm_host->calibration_done = false;
+ }
dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
@@ -634,6 +671,7 @@ 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);
struct mmc_ios curr_ios = host->mmc->ios;
+ u32 config;
int rc;
if (!clock) {
@@ -652,6 +690,70 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
(curr_ios.timing == MMC_TIMING_MMC_DDR52) ||
(curr_ios.timing == MMC_TIMING_MMC_HS400))
clock *= 2;
+ /*
+ * In general all timing modes are controlled via UHS mode select in
+ * Host Control2 register. eMMC specific HS200/HS400 doesn't have
+ * their respective modes defined here, hence we use these values.
+ *
+ * HS200 - SDR104 (Since they both are equivalent in functionality)
+ * HS400 - This involves multiple configurations
+ * Initially SDR104 - when tuning is required as HS200
+ * Then when switching to DDR @ 400MHz (HS400) we use
+ * the vendor specific HC_SELECT_IN to control the mode.
+ *
+ * In addition to controlling the modes we also need to select the
+ * correct input clock for DLL depending on the mode.
+ *
+ * HS400 - divided clock (free running MCLK/2)
+ * All other modes - default (free running MCLK)
+ */
+ if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
+ /* Select the divided clock (free running MCLK/2) */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_MCLK_SEL_MASK;
+ config |= CORE_HC_MCLK_SEL_HS400;
+
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ /*
+ * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+ * register
+ */
+ if (msm_host->tuning_done && !msm_host->calibration_done) {
+ /*
+ * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
+ * field in VENDOR_SPEC_FUNC
+ */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config |= CORE_HC_SELECT_IN_HS400;
+ config |= CORE_HC_SELECT_IN_EN;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+ } else {
+ /* Select the default clock (free running MCLK) */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_MCLK_SEL_MASK;
+ config |= CORE_HC_MCLK_SEL_DFLT;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+ /*
+ * Disable HC_SELECT_IN to be able to use the UHS mode select
+ * configuration from Host Control2 register for all other
+ * modes.
+ *
+ * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+ * in VENDOR_SPEC_FUNC
+ */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_SELECT_IN_EN;
+ config &= ~CORE_HC_SELECT_IN_MASK;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+
+ /*
+ * Make sure above writes impacting free running MCLK are completed
+ * before changing the clk_rate at GCC.
+ */
+ wmb();
if (clock != msm_host->clk_rate) {
rc = clk_set_rate(msm_host->clk, clock);
@@ -790,6 +892,11 @@ static int sdhci_msm_probe(struct platform_device *pdev)
/* Set HC_MODE_EN bit in HC_MODE register */
writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+ /* Set FF_CLK_SW_RST_DIS bit in HC_MODE register */
+ config = readl_relaxed(msm_host->core_mem + CORE_HC_MODE);
+ config |= FF_CLK_SW_RST_DIS;
+ writel_relaxed(config, msm_host->core_mem + CORE_HC_MODE);
+
host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 10/14] arm64: dts: qcom: msm8916: Add ddr support to sdhc1
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
shawn.lin-TNX95d0MmH7DzftRWevZcw, sboyd-sgV2jX0FEOL9JmXXK+q4OQ
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
david.brown-QSEj5FYQhm4dnm+yROfE0A,
andy.gross-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
david.griego-QSEj5FYQhm4dnm+yROfE0A,
stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
pramod.gurav-QSEj5FYQhm4dnm+yROfE0A, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
This adds mmc-ddr-1_8v support to DT for sdhc1 of msm8916.
Signed-off-by: Ritesh Harjani <riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 466ca57..ed15e87 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -514,6 +514,7 @@
clocks = <&gcc GCC_SDCC1_APPS_CLK>,
<&gcc GCC_SDCC1_AHB_CLK>;
clock-names = "core", "iface";
+ mmc-ddr-1_8v;
bus-width = <8>;
non-removable;
status = "disabled";
--
The 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 related
* [PATCH v6 09/14] mmc: sdhci-msm: Add clock changes for DDR mode.
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
SDHC MSM controller need 2x clock for MCLK at GCC.
Hence make required changes to have 2x clock for
DDR timing modes.
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index ff0915b..220567c 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -633,6 +633,7 @@ 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);
+ struct mmc_ios curr_ios = host->mmc->ios;
int rc;
if (!clock) {
@@ -641,11 +642,23 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
}
spin_unlock_irq(&host->lock);
+ /*
+ * The SDHC requires internal clock frequency to be double the
+ * actual clock that will be set for DDR mode. The controller
+ * uses the faster clock(100/400MHz) for some of its parts and
+ * send the actual required clock (50/200MHz) to the card.
+ */
+ if ((curr_ios.timing == MMC_TIMING_UHS_DDR50) ||
+ (curr_ios.timing == MMC_TIMING_MMC_DDR52) ||
+ (curr_ios.timing == MMC_TIMING_MMC_HS400))
+ clock *= 2;
+
if (clock != msm_host->clk_rate) {
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);
+ pr_err("%s: Failed to set clock at rate %u at timing %d\n",
+ mmc_hostname(host->mmc), clock,
+ curr_ios.timing);
spin_lock_irq(&host->lock);
goto out;
}
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 08/14] mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
sdhci-msm controller may have different clk-rates for each
bus speed mode. Thus implement set_clock callback for
sdhci-msm driver.
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 87 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 86 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index fde2777..ff0915b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -82,6 +82,7 @@ struct sdhci_msm_host {
struct clk *clk; /* main SD/MMC bus clock */
struct clk *pclk; /* SDHC peripheral bus clock */
struct clk *bus_clk; /* SDHC bus voter clock */
+ unsigned long clk_rate;
struct mmc_host *mmc;
bool use_14lpp_dll_reset;
};
@@ -573,6 +574,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);
+}
+
+/* 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) {
+ 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;
+ }
+ msm_host->clk_rate = clock;
+ pr_debug("%s: Setting clock at rate %lu\n",
+ mmc_hostname(host->mmc), clk_get_rate(msm_host->clk));
+ }
+ 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" },
{},
@@ -583,7 +668,7 @@ static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
static const struct sdhci_ops sdhci_msm_ops = {
.platform_execute_tuning = sdhci_msm_execute_tuning,
.reset = sdhci_reset,
- .set_clock = sdhci_set_clock,
+ .set_clock = sdhci_msm_set_clock,
.get_min_clock = sdhci_msm_get_min_clock,
.get_max_clock = sdhci_msm_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 07/14] mmc: sdhci-msm: Enable few quirks
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
sdhc-msm controller needs this SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
& SDHCI_QUIRK2_PRESET_VALUE_BROKEN to be set. Hence setting it.
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/host/sdhci-msm.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 66ca444..fde2777 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -594,7 +594,9 @@ static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
static const struct sdhci_pltfm_data sdhci_msm_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
SDHCI_QUIRK_NO_CARD_NO_RESET |
- SDHCI_QUIRK_SINGLE_POWER_WRITE,
+ SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.ops = &sdhci_msm_ops,
};
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 06/14] mmc: sdhci-msm: Add get_min_clock() and get_max_clock() callback
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
This add get_min_clock() and get_max_clock() callback
for sdhci-msm. sdhci-msm min/max clocks may be different
hence implement these callbacks.
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
drivers/mmc/host/sdhci-msm.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 32b0b79..66ca444 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -68,6 +68,7 @@
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
#define TCXO_FREQ 19200000
+#define SDHCI_MSM_MIN_CLOCK 400000
#define CDR_SELEXT_SHIFT 20
#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
@@ -559,6 +560,19 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+ return clk_round_rate(msm_host->clk, ULONG_MAX);
+}
+
+static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
+{
+ return SDHCI_MSM_MIN_CLOCK;
+}
+
static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -570,6 +584,8 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
.platform_execute_tuning = sdhci_msm_execute_tuning,
.reset = sdhci_reset,
.set_clock = sdhci_set_clock,
+ .get_min_clock = sdhci_msm_get_min_clock,
+ .get_max_clock = sdhci_msm_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.voltage_switch = sdhci_msm_voltage_switch,
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 05/14] mmc: sdhci-msm: Update DLL reset sequence
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
From: Venkat Gopalakrishnan <venkatg@codeaurora.org>
SDCC core with minor version >= 0x42 introduced new 14lpp
DLL. This has additional requirements in the reset sequence
for DLL tuning. Make necessary changes as needed.
Without this patch we see below errors on such SDHC controllers
sdhci_msm 7464900.sdhci: mmc0: DLL failed to LOCK
mmc0: tuning execution failed: -110
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/host/sdhci-msm.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 42f42aa..32b0b79 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -58,11 +58,17 @@
#define CORE_DLL_CONFIG 0x100
#define CORE_DLL_STATUS 0x108
+#define CORE_DLL_CONFIG_2 0x1b4
+#define CORE_FLL_CYCLE_CNT BIT(18)
+#define CORE_DLL_CLOCK_DISABLE BIT(21)
+
#define CORE_VENDOR_SPEC 0x10c
#define CORE_CLK_PWRSAVE BIT(1)
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
+#define TCXO_FREQ 19200000
+
#define CDR_SELEXT_SHIFT 20
#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
#define CMUX_SHIFT_PHASE_SHIFT 24
@@ -76,6 +82,7 @@ struct sdhci_msm_host {
struct clk *pclk; /* SDHC peripheral bus clock */
struct clk *bus_clk; /* SDHC bus voter clock */
struct mmc_host *mmc;
+ bool use_14lpp_dll_reset;
};
/* Platform specific tuning */
@@ -304,6 +311,8 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
static int msm_init_cm_dll(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
int wait_cnt = 50;
unsigned long flags;
u32 config = 0;
@@ -319,6 +328,16 @@ static int msm_init_cm_dll(struct sdhci_host *host)
config &= ~CORE_CLK_PWRSAVE;
writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ if (msm_host->use_14lpp_dll_reset) {
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config |= CORE_DLL_CLOCK_DISABLE;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ }
+
/* Write 1 to DLL_RST bit of DLL_CONFIG register */
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config |= CORE_DLL_RST;
@@ -330,6 +349,24 @@ static int msm_init_cm_dll(struct sdhci_host *host)
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
msm_cm_dll_set_freq(host);
+ if (msm_host->use_14lpp_dll_reset) {
+ u32 mclk_freq = 0;
+
+ if ((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
+ & CORE_FLL_CYCLE_CNT))
+ mclk_freq = (u32)((host->clock / TCXO_FREQ) * 8);
+ else
+ mclk_freq = (u32)((host->clock / TCXO_FREQ) * 4);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config &= ~(0xFF << 10);
+ config |= mclk_freq << 10;
+
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ /* wait for 5us before enabling DLL clock */
+ udelay(5);
+ }
+
/* Write 0 to DLL_RST bit of DLL_CONFIG register */
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config &= ~CORE_DLL_RST;
@@ -340,6 +377,14 @@ static int msm_init_cm_dll(struct sdhci_host *host)
config &= ~CORE_DLL_PDN;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ if (msm_host->use_14lpp_dll_reset) {
+ msm_cm_dll_set_freq(host);
+ /* Enable the DLL clock */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config &= ~CORE_DLL_CLOCK_DISABLE;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ }
+
/* Set DLL_EN bit to 1. */
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config |= CORE_DLL_EN;
@@ -641,6 +686,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
core_version, core_major, core_minor);
+ if ((core_major == 1) && (core_minor >= 0x42))
+ msm_host->use_14lpp_dll_reset = true;
+
/*
* Support for some capabilities is not advertised by newer
* controller versions and must be explicitly enabled.
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 04/14] mmc: sdhci-msm: Change poor style writel/readl of registers
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
shawn.lin-TNX95d0MmH7DzftRWevZcw, sboyd-sgV2jX0FEOL9JmXXK+q4OQ
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
david.brown-QSEj5FYQhm4dnm+yROfE0A,
andy.gross-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
david.griego-QSEj5FYQhm4dnm+yROfE0A,
stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
pramod.gurav-QSEj5FYQhm4dnm+yROfE0A, Ritesh Harjani
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
This patch changes the poor style of writel/readl registers
into more readable format. Also to avoid mixed style format
of readl/writel in sdhci-msm driver.
Signed-off-by: Ritesh Harjani <riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Adrian Hunter <adrian.hunter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/mmc/host/sdhci-msm.c | 54 ++++++++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 22 deletions(-)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 8ef44a2a..42f42aa 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,8 +137,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
rc = msm_dll_poll_ck_out_en(host, 1);
@@ -305,6 +306,7 @@ static int msm_init_cm_dll(struct sdhci_host *host)
struct mmc_host *mmc = host->mmc;
int wait_cnt = 50;
unsigned long flags;
+ u32 config = 0;
spin_lock_irqsave(&host->lock, flags);
@@ -313,33 +315,40 @@ static int msm_init_cm_dll(struct sdhci_host *host)
* tuning is in progress. Keeping PWRSAVE ON may
* turn off the clock.
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_CLK_PWRSAVE;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
/* Write 1 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
msm_cm_dll_set_freq(host);
/* Write 0 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Set DLL_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Set CK_OUT_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
@@ -536,7 +545,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
struct resource *core_memres;
int ret;
u16 host_version, core_minor;
- u32 core_version, caps;
+ u32 core_version, config;
u8 core_major;
host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
@@ -605,8 +614,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
}
/* Reset the core and Enable SDHC mode */
- writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
- CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+ config = readl_relaxed(msm_host->core_mem + CORE_POWER);
+ config |= CORE_SW_RST;
+ writel_relaxed(config, msm_host->core_mem + CORE_POWER);
/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
usleep_range(1000, 5000);
@@ -636,9 +646,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
* controller versions and must be explicitly enabled.
*/
if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
- caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
- caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
- writel_relaxed(caps, host->ioaddr +
+ config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
+ config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
+ writel_relaxed(config, host->ioaddr +
CORE_VENDOR_SPEC_CAPABILITIES0);
}
--
The 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 related
* [PATCH v6 03/14] clk: qcom: Move all sdcc rcgs to use clk_rcg2_floor_ops
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
From: Rajendra Nayak <rnayak@codeaurora.org>
The sdcc driver for msm8996/msm8916/msm8974 and apq8084
expects a clk_set_rate() on the sdcc rcg clk to set
a floor value of supported clk rate closest to the requested
rate, by looking up the frequency table.
So move all the sdcc rcgs on all these platforms to use the
newly introduced clk_rcg2_floor_ops
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
drivers/clk/qcom/gcc-apq8084.c | 8 ++++----
drivers/clk/qcom/gcc-msm8916.c | 4 ++--
drivers/clk/qcom/gcc-msm8974.c | 8 ++++----
drivers/clk/qcom/gcc-msm8996.c | 8 ++++----
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c
index 070037a..486d961 100644
--- a/drivers/clk/qcom/gcc-apq8084.c
+++ b/drivers/clk/qcom/gcc-apq8084.c
@@ -1142,7 +1142,7 @@ enum {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1156,7 +1156,7 @@ enum {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1170,7 +1170,7 @@ enum {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1184,7 +1184,7 @@ enum {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index 5c4e193..628e6ca 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -1107,7 +1107,7 @@ enum {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1132,7 +1132,7 @@ enum {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 0091520..348e30d 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -872,7 +872,7 @@ enum {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
};
static struct clk_rcg2 sdcc1_apps_clk_src = {
@@ -894,7 +894,7 @@ enum {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -908,7 +908,7 @@ enum {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -922,7 +922,7 @@ enum {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index fe03e6f..5adb163 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -460,7 +460,7 @@ enum {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
.num_parents = 4,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -497,7 +497,7 @@ enum {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -511,7 +511,7 @@ enum {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -535,7 +535,7 @@ enum {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 02/14] clk: qcom: Add rcg ops to return floor value closest to the requested rate
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org>
From: Rajendra Nayak <rnayak@codeaurora.org>
The default behaviour with clk_rcg2_ops is for the
clk_round_rate()/clk_set_rate() to return/set a ceil clock
rate closest to the requested rate by looking up the corresponding
frequency table.
However, we do have some instances (mainly sdcc on various platforms)
of clients expecting a clk_set_rate() to set a floor value instead.
Add a new clk_rcg2_floor_ops to handle this for such specific
rcg instances
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
drivers/clk/qcom/clk-rcg.h | 1 +
drivers/clk/qcom/clk-rcg2.c | 75 +++++++++++++++++++++++++++++++++++++++------
drivers/clk/qcom/common.c | 26 ++++++++++++++++
drivers/clk/qcom/common.h | 2 ++
4 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index b904c33..1b3e8d2 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -173,6 +173,7 @@ struct clk_rcg2 {
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_floor_ops;
extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_edp_pixel_ops;
extern const struct clk_ops clk_byte_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index a071bba..04433a6 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -47,6 +47,11 @@
#define N_REG 0xc
#define D_REG 0x10
+enum {
+ FLOOR,
+ CEIL,
+};
+
static int clk_rcg2_is_enabled(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -176,15 +181,25 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
return calc_rate(parent_rate, m, n, mode, hid_div);
}
-static int _freq_tbl_determine_rate(struct clk_hw *hw,
- const struct freq_tbl *f, struct clk_rate_request *req)
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+ struct clk_rate_request *req, bool match)
{
unsigned long clk_flags, rate = req->rate;
struct clk_hw *p;
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
int index;
- f = qcom_find_freq(f, rate);
+ switch (match) {
+ case FLOOR:
+ f = qcom_find_freq_floor(f, rate);
+ break;
+ case CEIL:
+ f = qcom_find_freq(f, rate);
+ break;
+ default:
+ return -EINVAL;
+ };
+
if (!f)
return -EINVAL;
@@ -221,7 +236,15 @@ static int clk_rcg2_determine_rate(struct clk_hw *hw,
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, CEIL);
+}
+
+static int clk_rcg2_determine_floor_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR);
}
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -265,12 +288,23 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
return update_config(rcg);
}
-static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+ bool match)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const struct freq_tbl *f;
- f = qcom_find_freq(rcg->freq_tbl, rate);
+ switch (match) {
+ case FLOOR:
+ f = qcom_find_freq_floor(rcg->freq_tbl, rate);
+ break;
+ case CEIL:
+ f = qcom_find_freq(rcg->freq_tbl, rate);
+ break;
+ default:
+ return -EINVAL;
+ };
+
if (!f)
return -EINVAL;
@@ -280,13 +314,25 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- return __clk_rcg2_set_rate(hw, rate);
+ return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return __clk_rcg2_set_rate(hw, rate, FLOOR);
}
static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate, u8 index)
{
- return __clk_rcg2_set_rate(hw, rate);
+ return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ return __clk_rcg2_set_rate(hw, rate, FLOOR);
}
const struct clk_ops clk_rcg2_ops = {
@@ -300,6 +346,17 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
};
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
+const struct clk_ops clk_rcg2_floor_ops = {
+ .is_enabled = clk_rcg2_is_enabled,
+ .get_parent = clk_rcg2_get_parent,
+ .set_parent = clk_rcg2_set_parent,
+ .recalc_rate = clk_rcg2_recalc_rate,
+ .determine_rate = clk_rcg2_determine_floor_rate,
+ .set_rate = clk_rcg2_set_floor_rate,
+ .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+
static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -323,7 +380,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
pr_err("%s: RCG did not turn on\n", name);
/* set clock rate */
- ret = __clk_rcg2_set_rate(hw, rate);
+ ret = __clk_rcg2_set_rate(hw, rate, CEIL);
if (ret)
return ret;
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index fffcbaf..cf6b87f 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -46,6 +46,32 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
}
EXPORT_SYMBOL_GPL(qcom_find_freq);
+const
+struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ unsigned long rate)
+{
+ int size = 0;
+
+ if (!f)
+ return NULL;
+
+ /*
+ * The freq table has entries in the ascending order of frequencies
+ * To find the floor for a given frequency, we need to do a reverse
+ * lookup of the table
+ */
+ for (; f->freq; f++, size++)
+ ;
+
+ for (f--; size; f--, size--)
+ if (rate >= f->freq)
+ return f;
+
+ /* could not find any rates lower than *rate* */
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
+
int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
{
int i, num_parents = clk_hw_get_num_parents(hw);
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index ae9bdeb..76886a1 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -34,6 +34,8 @@ struct qcom_cc_desc {
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
unsigned long rate);
+extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ unsigned long rate);
extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
u8 src);
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH v6 01/14] clk: Add clk_hw_get_clk() helper API to be used by clk providers
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
shawn.lin-TNX95d0MmH7DzftRWevZcw, sboyd-sgV2jX0FEOL9JmXXK+q4OQ
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
david.brown-QSEj5FYQhm4dnm+yROfE0A,
andy.gross-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
david.griego-QSEj5FYQhm4dnm+yROfE0A,
stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
pramod.gurav-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1478517877-23733-1-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
From: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Add a helper API that will allow clk providers to turn their clk_hw
structures into struct clk pointer.
Signed-off-by: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/clk/clk.c | 6 ++++++
include/linux/clk-provider.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0fb39fe..52ef035 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -186,6 +186,12 @@ const char *clk_hw_get_name(const struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_get_name);
+struct clk *clk_hw_get_clk(const struct clk_hw *hw)
+{
+ return hw->clk;
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_clk);
+
struct clk_hw *__clk_get_hw(struct clk *clk)
{
return !clk ? NULL : clk->core->hw;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index af59638..37022a9 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -729,6 +729,7 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
/* helper functions */
const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw);
+struct clk *clk_hw_get_clk(const struct clk_hw *hw);
struct clk_hw *__clk_get_hw(struct clk *clk);
unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
--
The 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 related
* [PATCH v6 00/14] mmc: sdhci-msm: Add clk-rates, DDR, HS400 support
From: Ritesh Harjani @ 2016-11-07 11:24 UTC (permalink / raw)
To: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, sboyd
Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
pramod.gurav, Ritesh Harjani
Hi,
This is v6 version of the patch series which adds support for MSM8996.
Adds HS400 driver support as well.
These are tested on internal msm8996 & db410c HW.
Changes from v5 -> v6 :-
1. Earlier in v5 series DT node was added to get the clk-rates table
needed for sdhci-msm driver. But this is removed in this(v6) patch series
and instead the clk changes are done in the clk driver as per Rob H comment.
2. Added clk driver changes(patch 1-3) to provide floor rate values of requested
clock for sdhc client.
For following boards- apq8084, msm8996, msm8916, msm8974.
3. Other minor patch comments were addressed.
Changes from v4 -> v5 :-
1. Added HS400 sdhci-msm controller specific changes:- (Patch 10, 11, 12)
2. Addressed comment from Adrian on Patch 07 @[3].
3. Addressed comment from Arnd on Patch 03, to directly add
clk_table into sdhci_msm_host. [4]
4. Addressed comment from Bjorn to not enforce having clk-rates property
in DT for older targets based on discussion at [5]
5. Retained Acks from Adrian on patches (01 & 02 & 06) where there were no
changes made while addressing above comments.
Older history:-
This is v4 version of the patch series.
Patches 01, 02, 05 & 06 were Acked-by Adrian.
Changes from v3 -> v4 :-
1. Addressed comments from Adrian on Patch 03, 07, 08.
2. Addressed comments from Bjorn on Patch 03.
3. Added clk-rate support for sdhc DT nodes to all MSM platforms.
in Pacth 04.
4. Rebased on next branch of Ulf.
Changes from v2 -> v3 :-
1. Addded Patch 01 based on Bjorn comment[2] -
This fixes/unrolls the poor coding style of read/writes of
registers from base sdhci-msm driver.
2. Fixed/unrolled poor style of reads/writes of registers in Patch 02,
based on Bjorn comment[2]. Also changed name of flag from
use_updated_dll_reset -> use_14lpp_dll_reset.
Changes from v1->v2 :-
1. Removed patch 06 & 08 from v1 patch series[1]
(which were introducing unnecessary quirks).
Instead have implemented __sdhci_msm_set_clock version of
sdhci_set_clock in sdhci_msm driver itself in patch 07 of
this patch series.
2. Enabled extra quirk (SDHCI_QUIRK2_PRESET_VALUE_BROKEN) in
patch 05 of this patch series.
Description of patches :-
This patchset adds clk-rates & other required changes to
upstream sdhci-msm driver from codeaurora tree.
It has been tested on a db410c Dragonboard and msm8996 based
platform.
Patch 0001-0003- Adds support in qcom clk driver to return
floor value of requested clock rate instead of ceil rate
for sdhc clients.
Patch 0004- Adds updated dll sequence for newer controllers
which has minor_version >= 0x42. This is required for msm8996.
MSM controller HW recommendation is to use the base MCI clock
and directly control this MCI clock at GCC in order to
change the clk-rate.
Patches 06-08 bring in required change for this to
sdhci-msm.
MSM controller would require 2x clock rate from source
for DDR bus speed modes. Patch 09 adds this support.
Patch 0010- adds DDR support in DT for sdhc1 of msm8916.
Patches 0011-0014- Adds HS400 support to sdhci-msm.
[1]:- http://www.spinics.net/lists/linux-mmc/msg38467.html
[2]:- http://www.spinics.net/lists/linux-mmc/msg38578.html
[3]:- https://patchwork.kernel.org/patch/9289345/
[4]:- https://www.spinics.net/lists/linux-mmc/msg39107.html
[5]:- http://www.spinics.net/lists/linux-mmc/msg38749.html
[6]:- https://patchwork.kernel.org/patch/9297381/
Rajendra Nayak (3):
clk: Add clk_hw_get_clk() helper API to be used by clk providers
clk: qcom: Add rcg ops to return floor value closest to the requested
rate
clk: qcom: Move all sdcc rcgs to use clk_rcg2_floor_ops
Ritesh Harjani (9):
mmc: sdhci-msm: Change poor style writel/readl of registers
mmc: sdhci-msm: Add get_min_clock() and get_max_clock() callback
mmc: sdhci-msm: Enable few quirks
mmc: sdhci-msm: Implement set_clock callback for sdhci-msm
mmc: sdhci-msm: Add clock changes for DDR mode.
arm64: dts: qcom: msm8916: Add ddr support to sdhc1
mmc: sdhci-msm: Save the calculated tuning phase
mmc: sdhci-msm: Add calibration tuning for CDCLP533 circuit
sdhci: sdhci-msm: update dll configuration
Venkat Gopalakrishnan (2):
mmc: sdhci-msm: Update DLL reset sequence
mmc: sdhci-msm: Add HS400 platform support
arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 +
drivers/clk/clk.c | 6 +
drivers/clk/qcom/clk-rcg.h | 1 +
drivers/clk/qcom/clk-rcg2.c | 75 +++-
drivers/clk/qcom/common.c | 26 ++
drivers/clk/qcom/common.h | 2 +
drivers/clk/qcom/gcc-apq8084.c | 8 +-
drivers/clk/qcom/gcc-msm8916.c | 4 +-
drivers/clk/qcom/gcc-msm8974.c | 8 +-
drivers/clk/qcom/gcc-msm8996.c | 8 +-
drivers/mmc/host/sdhci-msm.c | 650 ++++++++++++++++++++++++++++++++--
include/linux/clk-provider.h | 1 +
12 files changed, 733 insertions(+), 57 deletions(-)
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply
* Re: [PATCH v5 03/12] mmc: sdhci-msm: add pltfm_data support to get clk-rates from DT
From: Ritesh Harjani @ 2016-11-07 11:21 UTC (permalink / raw)
To: Rob Herring
Cc: Ulf Hansson, linux-mmc@vger.kernel.org, Adrian Hunter, Shawn Lin,
David Brown, Andy Gross, devicetree@vger.kernel.org,
linux-arm-msm, georgi.djakov, alex.lemberg, mateusz.nowak,
Yuliy.Izrailov, asutoshd, David Griego, Sahitya Tummala, venkatg,
Stephen Boyd, Bjorn Andersson, pramod.gurav, Rajendra Nayak
In-Reply-To: <CAL_JsqJbkDX3yAf6EGOcZiN=Fk-cz-7VeQxPK7_YOMyN7Pg0zA@mail.gmail.com>
Hi Rob,
On 10/11/2016 6:01 PM, Rob Herring wrote:
> On Tue, Oct 11, 2016 at 4:06 AM, Ritesh Harjani <riteshh@codeaurora.org> wrote:
>> Hi Rob
>>
>>
>> On 10/11/2016 12:59 AM, Rob Herring wrote:
>>>
>>> On Mon, Oct 10, 2016 at 11:07 AM, Ritesh Harjani <riteshh@codeaurora.org>
>>> wrote:
>>>>
>>>> Hi Rob,
>>>>
>>>> Thanks for review.
>>>>
>>>> On 10/10/2016 6:27 PM, Rob Herring wrote:
>>>>>
>>>>>
>>>>> On Wed, Oct 05, 2016 at 08:10:31PM +0530, Ritesh Harjani wrote:
>>>>>>
>>>>>>
>>>>>> This adds support for sdhc-msm controllers to get supported
>>>>>> clk-rates from DT. sdhci-msm would need it's own set_clock
>>>>>> ops to be implemented. For this, supported clk-rates needs
>>>>>> to be populated in sdhci_msm_pltfm_data.
>>>>>>
>>>>>> Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
>>>>>> ---
>>>>>> .../devicetree/bindings/mmc/sdhci-msm.txt | 1 +
>>>>>> drivers/mmc/host/sdhci-msm.c | 48
>>>>>> ++++++++++++++++++++++
>>>>>> 2 files changed, 49 insertions(+)
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>>>>>> b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>>>>>> index 485483a..6a83b38 100644
>>>>>> --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>>>>>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>>>>>> @@ -17,6 +17,7 @@ Required properties:
>>>>>> "iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock)
>>>>>> (required)
>>>>>> "core" - SDC MMC clock (MCLK) (required)
>>>>>> "bus" - SDCC bus voter clock (optional)
>>>>>> +- clk-rates: Array of supported GCC clock frequencies for sdhc, Units
>>>>>> -
>>>>>> Hz.
>>>>>
>>>>>
>>>>>
>>>>> Why can't some combination of assigned-clock-rates and querying the
>>>>> clock provider for rates be used here?
>>>>
>>>>
>>>> From what I understood, assigned-clock-rates would only work for setting
>>>> some default clock rates for certain clocks by calling
>>>> of_clk_set_defaults.
>>>>
>>>> Whereas the requirement here is -
>>>> That since SDHC msm directly controls the clk(core clock) at source, it's
>>>> sdhci-msm driver needs to know the supported clk-rates by the underlying
>>>> platform to configure the nearest floor value supported on this platform
>>>> (when the request arrives from the core layer to switch the clock).
>>>
>>>
>>> Why does clk_round_rate not work for you? That will round down to the
>>> nearest frequency supported.
>>
>> clk_round_rate will round off to nearest supported "ceil" frequency.
>> But we require nearest rounded off "floor" frequency.
>
> Then fix the clk framework to do what you want. This doesn't need to be in DT.
Sure. Discussed with clk driver. Will make the required changes in qcom
clk driver to fix this.
Will soon publish the new series.
>
> Rob
> --
> 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
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH] PM / Domains: Fix compatible for domain idle state
From: Ulf Hansson @ 2016-11-07 11:14 UTC (permalink / raw)
To: Lina Iyer
Cc: Kevin Hilman, Rafael J. Wysocki, linux-pm@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Andy Gross, Stephen Boyd,
linux-arm-msm@vger.kernel.org, Brendan Jackman, Lorenzo Pieralisi,
Sudeep Holla, Juri Lelli, devicetree@vger.kernel.org, Rob Herring
In-Reply-To: <1478210075-92045-2-git-send-email-lina.iyer@linaro.org>
On 3 November 2016 at 22:54, Lina Iyer <lina.iyer@linaro.org> wrote:
> Re-using idle state definition provided by arm,idle-state for domain
> idle states creates a lot of confusion and limits further evolution of
> the domain idle definition. To keep things clear and simple, define a
> idle states for domain using a new compatible "domain-idle-state".
>
> Fix existing PM domains code to look for the newly defined compatible.
>
> Cc: <devicetree@vger.kernel.org>
> Cc: Rob Herring <robh@kernel.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> ---
> .../bindings/power/domain-idle-state.txt | 33 ++++++++++++++++++++++
> .../devicetree/bindings/power/power_domain.txt | 8 +++---
> drivers/base/power/domain.c | 2 +-
> 3 files changed, 38 insertions(+), 5 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/power/domain-idle-state.txt
>
> diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.txt b/Documentation/devicetree/bindings/power/domain-idle-state.txt
> new file mode 100644
> index 0000000..eefc7ed
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/domain-idle-state.txt
> @@ -0,0 +1,33 @@
> +PM Domain Idle State Node:
> +
> +A domain idle state node represents the state parameters that will be used to
> +select the state when there are no active components in the domain.
> +
> +The state node has the following parameters -
> +
> +- compatible:
> + Usage: Required
> + Value type: <string>
> + Definition: Must be "domain-idle-state".
> +
> +- entry-latency-us
> + Usage: Required
> + Value type: <prop-encoded-array>
> + Definition: u32 value representing worst case latency in
> + microseconds required to enter the idle state.
> + The exit-latency-us duration may be guaranteed
> + only after entry-latency-us has passed.
As we anyway are going to change this, why not use an u64 and have the
value in ns instead of us?
That should give us better flexibility and I think this would also be
what Rob would recommend, if I remember earlier similar comments from
him.
> +
> +- exit-latency-us
> + Usage: Required
> + Value type: <prop-encoded-array>
> + Definition: u32 value representing worst case latency
> + in microseconds required to exit the idle state.
Ditto.
> +
> +- min-residency-us
> + Usage: Required
> + Value type: <prop-encoded-array>
> + Definition: u32 value representing minimum residency duration
> + in microseconds after which the idle state will yield
> + power benefits after overcoming the overhead in entering
> +i the idle state.
Ditto.
> diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
> index e165036..723e1ad 100644
> --- a/Documentation/devicetree/bindings/power/power_domain.txt
> +++ b/Documentation/devicetree/bindings/power/power_domain.txt
> @@ -31,7 +31,7 @@ Optional properties:
>
> - domain-idle-states : A phandle of an idle-state that shall be soaked into a
> generic domain power state. The idle state definitions are
> - compatible with arm,idle-state specified in [1].
> + compatible with domain-idle-state specified in [1].
> The domain-idle-state property reflects the idle state of this PM domain and
> not the idle states of the devices or sub-domains in the PM domain. Devices
> and sub-domains have their own idle-states independent of the parent
> @@ -85,7 +85,7 @@ Example 3:
> };
>
> DOMAIN_RET: state@0 {
> - compatible = "arm,idle-state";
> + compatible = "domain-idle-state";
> reg = <0x0>;
> entry-latency-us = <1000>;
> exit-latency-us = <2000>;
> @@ -93,7 +93,7 @@ Example 3:
> };
>
> DOMAIN_PWR_DN: state@1 {
> - compatible = "arm,idle-state";
> + compatible = "domain-idle-state";
> reg = <0x1>;
> entry-latency-us = <5000>;
> exit-latency-us = <8000>;
> @@ -118,4 +118,4 @@ The node above defines a typical PM domain consumer device, which is located
> inside a PM domain with index 0 of a power controller represented by a node
> with the label "power".
>
> -[1]. Documentation/devicetree/bindings/arm/idle-states.txt
> +[1]. Documentation/devicetree/bindings/power/domain-idle-state.txt
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index 661737c..f0bc672 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -2048,7 +2048,7 @@ int genpd_dev_pm_attach(struct device *dev)
> EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
>
> static const struct of_device_id idle_state_match[] = {
> - { .compatible = "arm,idle-state", },
> + { .compatible = "domain-idle-state", },
> { }
> };
>
> --
> 2.7.4
>
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH V4 6/6] bus: Add support for Tegra Generic Memory Interface
From: Jon Hunter @ 2016-11-07 11:13 UTC (permalink / raw)
To: Mirza Krak, swarren, thierry.reding
Cc: gnurou, linux, pdeschrijver, pgaikwad, mturquette, sboyd, robh+dt,
mark.rutland, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, linux-clk
In-Reply-To: <1478507405-13204-7-git-send-email-mirza.krak@gmail.com>
On 07/11/16 08:30, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> The Generic Memory Interface bus can be used to connect high-speed
> devices such as NOR flash, FPGAs, DSPs...
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
Thanks for the update.
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCH v5] media: et8ek8: add device tree binding documentation
From: Pavel Machek @ 2016-11-07 10:46 UTC (permalink / raw)
To: Rob Herring
Cc: ivo.g.dimitrov.75, sakari.ailus, sre, pali.rohar, linux-media,
pawel.moll, mark.rutland, ijc+devicetree, galak, mchehab,
devicetree, linux-kernel
In-Reply-To: <20161030204134.hpmfrnqhd4mg563o@rob-hp-laptop>
[-- Attachment #1: Type: text/plain, Size: 2098 bytes --]
Add device tree binding documentation for toshiba et8ek8 sensor.
Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Signed-off-by: Pavel Machek <pavel@ucw.cz>
diff --git a/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt
new file mode 100644
index 0000000..b03b21d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt
@@ -0,0 +1,53 @@
+Toshiba et8ek8 5MP sensor
+
+Toshiba et8ek8 5MP sensor is an image sensor found in Nokia N900 device
+
+More detailed documentation can be found in
+Documentation/devicetree/bindings/media/video-interfaces.txt .
+
+
+Mandatory properties
+--------------------
+
+- compatible: "toshiba,et8ek8"
+- reg: I2C address (0x3e, or an alternative address)
+- vana-supply: Analogue voltage supply (VANA), 2.8 volts
+- clocks: External clock to the sensor
+- clock-frequency: Frequency of the external clock to the sensor. Camera
+ driver will set this frequency on the external clock. The clock frequency is
+ a pre-determined frequency known to be suitable to the board.
+- reset-gpios: XSHUTDOWN GPIO. The XSHUTDOWN signal is active high. The sensor
+ is in hardware standby mode when the signal is in low state.
+
+
+Endpoint node mandatory properties
+----------------------------------
+
+- remote-endpoint: A phandle to the bus receiver's endpoint node.
+
+Endpoint node optional properties
+----------------------------------
+
+- clock-lanes: <0>
+- data-lanes: <1..n>
+
+Example
+-------
+
+&i2c3 {
+ clock-frequency = <400000>;
+
+ cam1: camera@3e {
+ compatible = "toshiba,et8ek8";
+ reg = <0x3e>;
+ vana-supply = <&vaux4>;
+ clocks = <&isp 0>;
+ clock-frequency = <9600000>;
+ reset-gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* 102 */
+ port {
+ csi_cam1: endpoint {
+ remote-endpoint = <&csi_out1>;
+ };
+ };
+ };
+};
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply related
* [PATCH 3/3] ARM64: dts: meson-gxl-s905x: Enable internal ethernet PHY
From: Neil Armstrong @ 2016-11-07 10:43 UTC (permalink / raw)
To: khilman, carlo
Cc: Neil Armstrong, linux-amlogic, linux-arm-kernel, linux-kernel,
devicetree
In-Reply-To: <20161107104357.24428-1-narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi
index 07f0e0b..08237ee 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi
@@ -46,3 +46,9 @@
/ {
compatible = "amlogic,s905x", "amlogic,meson-gxl";
};
+
+/* S905X Only has access to its internal PHY */
+ðmac {
+ phy-mode = "rmii";
+ phy-handle = <&internal_phy>;
+};
--
2.7.0
^ permalink raw reply related
* [PATCH 2/3] ARM64: dts: meson-gxl-p23x: Enable ethernet
From: Neil Armstrong @ 2016-11-07 10:43 UTC (permalink / raw)
To: khilman, carlo
Cc: linux-amlogic, devicetree, linux-kernel, linux-arm-kernel,
Neil Armstrong
In-Reply-To: <20161107104357.24428-1-narmstrong@baylibre.com>
Enable Ethernet on the p23x board, pinctrl attribute is only added for
the p230 board since the p231 only uses the Internal PHY.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
.../boot/dts/amlogic/meson-gxl-s905d-p230.dts | 25 ++++++++++++++++++++++
.../boot/dts/amlogic/meson-gxl-s905d-p231.dts | 6 ++++++
.../boot/dts/amlogic/meson-gxl-s905d-p23x.dtsi | 4 ++++
3 files changed, 35 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
index 3dfaa37..4d082a7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
@@ -49,3 +49,28 @@
compatible = "amlogic,p230", "amlogic,s905d", "amlogic,meson-gxl";
model = "Amlogic Meson GXL (S905D) P230 Development Board";
};
+
+/* P230 has exclusive choice between internal or external PHY */
+ðmac {
+ pinctrl-0 = <ð_pins>;
+ pinctrl-names = "default";
+
+ /* Select external PHY by default */
+ phy-handle = <&external_phy>;
+
+ /* External PHY reset is shared with internal PHY Led signals */
+ snps,reset-gpio = <&gpio GPIOZ_14 0>;
+ snps,reset-delays-us = <0 10000 1000000>;
+ snps,reset-active-low;
+
+ /* External PHY is in RGMII */
+ phy-mode = "rgmii";
+};
+
+&external_mdio {
+ external_phy: ethernet-phy@0 {
+ compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ max-speed = <1000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts
index ade8d29..1cc8d49 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts
@@ -49,3 +49,9 @@
compatible = "amlogic,p231", "amlogic,s905d", "amlogic,meson-gxl";
model = "Amlogic Meson GXL (S905D) P231 Development Board";
};
+
+/* P231 has only internal PHY port */
+ðmac {
+ phy-mode = "rmii";
+ phy-handle = <&internal_phy>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p23x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p23x.dtsi
index bbe46a2..622ffbe 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p23x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p23x.dtsi
@@ -182,3 +182,7 @@
clocks = <&clkc CLKID_FCLK_DIV4>;
clock-names = "clkin0";
};
+
+ðmac {
+ status = "okay";
+};
--
2.7.0
^ permalink raw reply related
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