From Chaotian.Jing at mediatek.com  Fri Apr  3 00:22:45 2015
From: Chaotian.Jing at mediatek.com (=?utf-8?B?Q2hhb3RpYW4gSmluZyAo5LqV5pyd5aSpKQ==?=)
Date: Fri, 3 Apr 2015 07:22:45 +0000
Subject: =?utf-8?B?562U5aSNOiBbUEFUQ0ggdjIgMi81XSBtbWM6IG1lZGlhdGVrOiBBZGQgTWVk?=
 =?utf-8?Q?iatek_MMC_driver?=
In-Reply-To: <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
Message-ID: <B077351396223C4F8FE8C4C13672A9CA609795F3@mtkmbs33n1>

Dear Ulf,

Thanks for your review!
Please help to check my comment.

> -----????-----
> ???: Ulf Hansson [mailto:ulf.hansson at linaro.org]
> ????: 2015?3?31? 20:23
> ???: Chaotian Jing (???)
> ??: Rob Herring; Matthias Brugger; Chris Ball; Mark Rutland; JamesJJ Liao
> (???); srv_heupstream; Arnd Bergmann; devicetree at vger.kernel.org;
> HONGZHOU Yang; Catalin Marinas; linux-mmc; Will Deacon;
> linux-kernel at vger.kernel.org; linux-gpio at vger.kernel.org; Sascha Hauer;
> Yingjoe Chen (???); Eddie Huang (???); Bin Zhang (??);
> linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org
> ??: Re: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
> 
> On 17 March 2015 at 04:13, Chaotian Jing <chaotian.jing at mediatek.com>
> wrote:
> > Add Mediatek MMC driver code
> 
> Would be nice to get simple overview of what features the
> driver/controller supports. Please add that to the commit message.
> 
Ok, will add it at next revision.
> >
> > Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> > ---
> >  drivers/mmc/host/Kconfig  |    8 +
> >  drivers/mmc/host/Makefile |    1 +
> >  drivers/mmc/host/mtk-sd.c | 1412
> +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 1421 insertions(+)
> >  create mode 100644 drivers/mmc/host/mtk-sd.c
> >
> > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> > index 61ac63a..8b64377 100644
> > --- a/drivers/mmc/host/Kconfig
> > +++ b/drivers/mmc/host/Kconfig
> > @@ -768,3 +768,11 @@ config MMC_TOSHIBA_PCI
> >         tristate "Toshiba Type A SD/MMC Card Interface Driver"
> >         depends on PCI
> >         help
> > +
> > +config MMC_MTK
> > +       tristate "MediaTek SD/MMC Card Interface support"
> > +       help
> > +         This selects the MediaTek(R) Secure digital and Multimedia card
> Interface.
> > +         If you have a machine with a integrated SD/MMC card reader,
> say Y or M here.
> > +         This is needed if support for any SD/SDIO/MMC devices is
> required.
> > +         If unsure, say N.
> > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> > index 6a7cfe0..161b3e4 100644
> > --- a/drivers/mmc/host/Makefile
> > +++ b/drivers/mmc/host/Makefile
> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30)       +=
> sdhci_f_sdh30.o
> >  obj-$(CONFIG_MMC_SDHCI_SPEAR)  += sdhci-spear.o
> >  obj-$(CONFIG_MMC_WBSD)         += wbsd.o
> >  obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
> > +obj-$(CONFIG_MMC_MTK)           += mtk-sd.o
> >  obj-$(CONFIG_MMC_OMAP)         += omap.o
> >  obj-$(CONFIG_MMC_OMAP_HS)      += omap_hsmmc.o
> >  obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > new file mode 100644
> > index 0000000..86c999b
> > --- /dev/null
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -0,0 +1,1412 @@
> > +/*
> > + * Copyright (c) 2014-2015 MediaTek Inc.
> > + * Author: Chaotian.Jing <chaotian.jing at mediatek.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.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/ioport.h>
> > +#include <linux/irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_gpio.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/spinlock.h>
> > +
> > +#include <linux/mmc/card.h>
> > +#include <linux/mmc/core.h>
> > +#include <linux/mmc/host.h>
> > +#include <linux/mmc/mmc.h>
> > +#include <linux/mmc/sd.h>
> > +#include <linux/mmc/sdio.h>
> > +
> > +#define MAX_GPD_NUM         (1 + 1)    /* one null gpd */
> > +#define MAX_BD_NUM          1024
> > +#define MAX_BD_PER_GPD      MAX_BD_NUM
> > +
> > +/*--------------------------------------------------------------------------*/
> > +/* Common Definition
> */
> > +/*--------------------------------------------------------------------------*/
> > +#define MSDC_MS                 0
> > +#define MSDC_SDMMC              1
> 
> Please convert to hex values.
Ok, will fix at next revision.
> 
> > +
> > +#define MSDC_BUS_1BITS          0
> > +#define MSDC_BUS_4BITS          1
> > +#define MSDC_BUS_8BITS          2
> 
> Please convert to hex values.
> 
Ok, will fix at next revision.
> > +
> > +#define MSDC_BURST_8B           3
> > +#define MSDC_BURST_16B          4
> > +#define MSDC_BURST_32B          5
> > +#define MSDC_BURST_64B          6
> 
> I don't find the first three being used, should we remove them?
> 
> Also, I think converting them to hex values make sense.
> 
Ok, will remove them and convert it to hex value
> 
> > +
> > +/*--------------------------------------------------------------------------*/
> > +/* Register Offset
> */
> > +/*--------------------------------------------------------------------------*/
> > +#define MSDC_CFG         0x0
> > +#define MSDC_IOCON       0x04
> > +#define MSDC_PS          0x08
> > +#define MSDC_INT         0x0c
> > +#define MSDC_INTEN       0x10
> > +#define MSDC_FIFOCS      0x14
> > +#define SDC_CFG          0x30
> > +#define SDC_CMD          0x34
> > +#define SDC_ARG          0x38
> > +#define SDC_STS          0x3c
> > +#define SDC_RESP0        0x40
> > +#define SDC_RESP1        0x44
> > +#define SDC_RESP2        0x48
> > +#define SDC_RESP3        0x4c
> > +#define SDC_BLK_NUM      0x50
> > +#define SDC_ACMD_RESP    0x80
> > +#define MSDC_DMA_SA      0x90
> > +#define MSDC_DMA_CTRL    0x98
> > +#define MSDC_DMA_CFG     0x9c
> > +#define MSDC_PATCH_BIT   0xb0
> > +#define MSDC_PATCH_BIT1  0xb4
> > +#define MSDC_PAD_TUNE    0xec
> > +
> > +/*--------------------------------------------------------------------------*/
> > +/* Register Mask
> */
> > +/*--------------------------------------------------------------------------*/
> > +
> > +/* MSDC_CFG mask */
> > +#define MSDC_CFG_MODE           (1 << 0)       /* RW */
> > +#define MSDC_CFG_CKPDN          (1 << 1)       /* RW */
> > +#define MSDC_CFG_RST            (1 << 2)       /* RW */
> > +#define MSDC_CFG_PIO            (1 << 3)       /* RW */
> > +#define MSDC_CFG_CKDRVEN        (1 << 4)       /* RW */
> > +#define MSDC_CFG_BV18SDT        (1 << 5)       /* RW */
> > +#define MSDC_CFG_BV18PSS        (1 << 6)       /* R  */
> > +#define MSDC_CFG_CKSTB          (1 << 7)       /* R  */
> > +#define MSDC_CFG_CKDIV          (0xff << 8)    /* RW */
> > +#define MSDC_CFG_CKMOD          (0x3 << 16)    /* RW */
> > +
> > +/* MSDC_IOCON mask */
> > +#define MSDC_IOCON_SDR104CKS    (1 << 0)       /* RW */
> > +#define MSDC_IOCON_RSPL         (1 << 1)       /* RW */
> > +#define MSDC_IOCON_DSPL         (1 << 2)       /* RW */
> > +#define MSDC_IOCON_DDLSEL       (1 << 3)       /* RW */
> > +#define MSDC_IOCON_DDR50CKD     (1 << 4)       /* RW */
> > +#define MSDC_IOCON_DSPLSEL      (1 << 5)       /* RW */
> > +#define MSDC_IOCON_W_DSPL       (1 << 8)       /* RW */
> > +#define MSDC_IOCON_D0SPL        (1 << 16)      /* RW */
> > +#define MSDC_IOCON_D1SPL        (1 << 17)      /* RW */
> > +#define MSDC_IOCON_D2SPL        (1 << 18)      /* RW */
> > +#define MSDC_IOCON_D3SPL        (1 << 19)      /* RW */
> > +#define MSDC_IOCON_D4SPL        (1 << 20)      /* RW */
> > +#define MSDC_IOCON_D5SPL        (1 << 21)      /* RW */
> > +#define MSDC_IOCON_D6SPL        (1 << 22)      /* RW */
> > +#define MSDC_IOCON_D7SPL        (1 << 23)      /* RW */
> > +#define MSDC_IOCON_RISCSZ       (0x3 << 24)    /* RW */
> > +
> > +/* MSDC_PS mask */
> > +#define MSDC_PS_CDEN            (1 << 0)       /* RW */
> > +#define MSDC_PS_CDSTS           (1 << 1)       /* R  */
> > +#define MSDC_PS_CDDEBOUNCE      (0xf << 12)    /* RW */
> > +#define MSDC_PS_DAT             (0xff << 16)   /* R  */
> > +#define MSDC_PS_CMD             (1 << 24)      /* R  */
> > +#define MSDC_PS_WP              (1 << 31)      /* R  */
> > +
> > +/* MSDC_INT mask */
> > +#define MSDC_INT_MMCIRQ         (1 << 0)       /* W1C */
> > +#define MSDC_INT_CDSC           (1 << 1)       /* W1C */
> > +#define MSDC_INT_ACMDRDY        (1 << 3)       /* W1C */
> > +#define MSDC_INT_ACMDTMO        (1 << 4)       /* W1C */
> > +#define MSDC_INT_ACMDCRCERR     (1 << 5)       /* W1C */
> > +#define MSDC_INT_DMAQ_EMPTY     (1 << 6)       /* W1C */
> > +#define MSDC_INT_SDIOIRQ        (1 << 7)       /* W1C */
> > +#define MSDC_INT_CMDRDY         (1 << 8)       /* W1C */
> > +#define MSDC_INT_CMDTMO         (1 << 9)       /* W1C */
> > +#define MSDC_INT_RSPCRCERR      (1 << 10)      /* W1C */
> > +#define MSDC_INT_CSTA           (1 << 11)      /* R */
> > +#define MSDC_INT_XFER_COMPL     (1 << 12)      /* W1C */
> > +#define MSDC_INT_DXFER_DONE     (1 << 13)      /* W1C */
> > +#define MSDC_INT_DATTMO         (1 << 14)      /* W1C */
> > +#define MSDC_INT_DATCRCERR      (1 << 15)      /* W1C */
> > +#define MSDC_INT_ACMD19_DONE    (1 << 16)      /* W1C */
> > +#define MSDC_INT_DMA_BDCSERR    (1 << 17)      /* W1C */
> > +#define MSDC_INT_DMA_GPDCSERR   (1 << 18)      /* W1C */
> > +#define MSDC_INT_DMA_PROTECT    (1 << 19)      /* W1C */
> > +
> > +/* MSDC_INTEN mask */
> > +#define MSDC_INTEN_MMCIRQ       (1 << 0)       /* RW */
> > +#define MSDC_INTEN_CDSC         (1 << 1)       /* RW */
> > +#define MSDC_INTEN_ACMDRDY      (1 << 3)       /* RW */
> > +#define MSDC_INTEN_ACMDTMO      (1 << 4)       /* RW */
> > +#define MSDC_INTEN_ACMDCRCERR   (1 << 5)       /* RW */
> > +#define MSDC_INTEN_DMAQ_EMPTY   (1 << 6)       /* RW */
> > +#define MSDC_INTEN_SDIOIRQ      (1 << 7)       /* RW */
> > +#define MSDC_INTEN_CMDRDY       (1 << 8)       /* RW */
> > +#define MSDC_INTEN_CMDTMO       (1 << 9)       /* RW */
> > +#define MSDC_INTEN_RSPCRCERR    (1 << 10)      /* RW */
> > +#define MSDC_INTEN_CSTA         (1 << 11)      /* RW */
> > +#define MSDC_INTEN_XFER_COMPL   (1 << 12)      /* RW */
> > +#define MSDC_INTEN_DXFER_DONE   (1 << 13)      /* RW */
> > +#define MSDC_INTEN_DATTMO       (1 << 14)      /* RW */
> > +#define MSDC_INTEN_DATCRCERR    (1 << 15)      /* RW */
> > +#define MSDC_INTEN_ACMD19_DONE  (1 << 16)      /* RW */
> > +#define MSDC_INTEN_DMA_BDCSERR  (1 << 17)      /* RW */
> > +#define MSDC_INTEN_DMA_GPDCSERR (1 << 18)      /* RW */
> > +#define MSDC_INTEN_DMA_PROTECT  (1 << 19)      /* RW */
> > +
> > +/* MSDC_FIFOCS mask */
> > +#define MSDC_FIFOCS_RXCNT       (0xff << 0)    /* R */
> > +#define MSDC_FIFOCS_TXCNT       (0xff << 16)   /* R */
> > +#define MSDC_FIFOCS_CLR         (1 << 31)      /* RW */
> > +
> > +/* SDC_CFG mask */
> > +#define SDC_CFG_SDIOINTWKUP     (1 << 0)       /* RW */
> > +#define SDC_CFG_INSWKUP         (1 << 1)       /* RW */
> > +#define SDC_CFG_BUSWIDTH        (0x3 << 16)    /* RW */
> > +#define SDC_CFG_SDIO            (1 << 19)      /* RW */
> > +#define SDC_CFG_SDIOIDE         (1 << 20)      /* RW */
> > +#define SDC_CFG_INTATGAP        (1 << 21)      /* RW */
> > +#define SDC_CFG_DTOC            (0xff << 24)   /* RW */
> > +
> > +/* SDC_STS mask */
> > +#define SDC_STS_SDCBUSY         (1 << 0)       /* RW */
> > +#define SDC_STS_CMDBUSY         (1 << 1)       /* RW */
> > +#define SDC_STS_SWR_COMPL       (1 << 31)      /* RW */
> > +
> > +/* MSDC_DMA_CTRL mask */
> > +#define MSDC_DMA_CTRL_START     (1 << 0)       /* W */
> > +#define MSDC_DMA_CTRL_STOP      (1 << 1)       /* W */
> > +#define MSDC_DMA_CTRL_RESUME    (1 << 2)       /* W */
> > +#define MSDC_DMA_CTRL_MODE      (1 << 8)       /* RW */
> > +#define MSDC_DMA_CTRL_LASTBUF   (1 << 10)      /* RW */
> > +#define MSDC_DMA_CTRL_BRUSTSZ   (0x7 << 12)    /* RW */
> > +
> > +/* MSDC_DMA_CFG mask */
> > +#define MSDC_DMA_CFG_STS        (1 << 0)       /* R */
> > +#define MSDC_DMA_CFG_DECSEN     (1 << 1)       /* RW */
> > +#define MSDC_DMA_CFG_AHBHPROT2  (0x2 << 8)     /* RW */
> > +#define MSDC_DMA_CFG_ACTIVEEN   (0x2 << 12)    /* RW */
> > +#define MSDC_DMA_CFG_CS12B16B   (1 << 16)      /* RW */
> > +
> > +/* MSDC_PATCH_BIT mask */
> > +#define MSDC_PATCH_BIT_ODDSUPP    (1 <<  1)    /* RW */
> > +#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 <<  7)
> > +#define MSDC_CKGEN_MSDC_DLY_SEL   (0x1f << 10)
> > +#define MSDC_PATCH_BIT_IODSSEL    (1 << 16)    /* RW */
> > +#define MSDC_PATCH_BIT_IOINTSEL   (1 << 17)    /* RW */
> > +#define MSDC_PATCH_BIT_BUSYDLY    (0xf << 18)  /* RW */
> > +#define MSDC_PATCH_BIT_WDOD       (0xf << 22)  /* RW */
> > +#define MSDC_PATCH_BIT_IDRTSEL    (1 << 26)    /* RW */
> > +#define MSDC_PATCH_BIT_CMDFSEL    (1 << 27)    /* RW */
> > +#define MSDC_PATCH_BIT_INTDLSEL   (1 << 28)    /* RW */
> > +#define MSDC_PATCH_BIT_SPCPUSH    (1 << 29)    /* RW */
> > +#define MSDC_PATCH_BIT_DECRCTMO   (1 << 30)    /* RW */
> > +
> > +#define REQ_CMD_EIO  (1 << 0)
> > +#define REQ_CMD_TMO  (1 << 1)
> > +#define REQ_DAT_ERR  (1 << 2)
> > +#define REQ_STOP_EIO (1 << 3)
> > +#define REQ_STOP_TMO (1 << 4)
> > +#define REQ_CMD_BUSY (1 << 5)
> > +
> > +#define MSDC_PREPARE_FLAG (1 << 0)
> > +#define MSDC_ASYNC_FLAG (1 << 1)
> > +#define MSDC_MMAP_FLAG (1 << 2)
> > +
> > +#define HOST_MAX_BLKSZ      2048
> > +#define MSDC_OCR_AVAIL      (MMC_VDD_28_29 | MMC_VDD_29_30 \
> > +               | MMC_VDD_30_31 | MMC_VDD_31_32 |
> MMC_VDD_32_33)
> 
> Both these aren't used. Remove please.
> 
Ok, will remove it at next revision.
> > +
> > +#define CMD_TIMEOUT         (HZ/10 * 5)        /* 100ms x5 */
> > +#define DAT_TIMEOUT         (HZ    * 5)        /* 1000ms x5 */
> > +
> > +/*--------------------------------------------------------------------------*/
> > +/* Descriptor Structure
> */
> > +/*--------------------------------------------------------------------------*/
> > +struct mt_gpdma_desc {
> > +       u32 first_u32;
> > +#define GPDMA_DESC_HWO         (1 << 0)
> > +#define GPDMA_DESC_BDP         (1 << 1)
> > +#define GPDMA_DESC_CHECKSUM    (0xff << 8) /* bit8 ~ bit15 */
> > +#define GPDMA_DESC_INT         (1 << 16)
> > +       u32 next;
> > +       u32 ptr;
> > +       u32 second_u32;
> > +#define GPDMA_DESC_BUFLEN      (0xffff) /* bit0 ~ bit15 */
> > +#define GPDMA_DESC_EXTLEN      (0xff << 16) /* bit16 ~ bit23 */
> > +       u32 arg;
> > +       u32 blknum;
> > +       u32 cmd;
> > +};
> > +
> > +struct mt_bdma_desc {
> > +       u32 first_u32;
> > +#define BDMA_DESC_EOL          (1 << 0)
> > +#define BDMA_DESC_CHECKSUM     (0xff << 8) /* bit8 ~ bit15 */
> > +#define BDMA_DESC_BLKPAD       (1 << 17)
> > +#define BDMA_DESC_DWPAD                (1 << 18)
> > +       u32 next;
> > +       u32 ptr;
> > +       u32 second_u32;
> > +#define BDMA_DESC_BUFLEN       (0xffff) /* bit0 ~ bit15 */
> > +};
> > +
> > +struct msdc_dma {
> > +       struct scatterlist *sg; /* I/O scatter list */
> > +       struct mt_gpdma_desc *gpd;              /* pointer to gpd
> array */
> > +       struct mt_bdma_desc *bd;                /* pointer to bd
> array */
> > +       dma_addr_t gpd_addr;    /* the physical address of gpd array */
> > +       dma_addr_t bd_addr;     /* the physical address of bd array */
> > +};
> 
> This looks weird from DMA perspective. Can you elaborate on why you
> can't use the dmaengine API?
> 
The gpd and bd structure are determined by the MSDC hw, and, the DMA controller is a part of the MSDC hw, different with the chain dma implemented by the kernel.
> > +
> > +struct msdc_host {
> > +       struct device *dev;
> > +       struct mmc_host *mmc;   /* mmc structure */
> > +       int cmd_rsp;
> > +
> > +       spinlock_t lock;
> > +       struct mmc_request *mrq;
> > +       struct mmc_command *cmd;
> > +       struct mmc_data *data;
> > +       int error;
> > +
> > +       void __iomem *base;             /* host base address */
> > +
> > +       struct msdc_dma dma;    /* dma channel */
> > +
> > +       u32 timeout_ns;         /* data timeout ns */
> > +       u32 timeout_clks;       /* data timeout clks */
> > +
> > +       struct pinctrl *pinctrl;
> > +       struct pinctrl_state *pins_default;
> > +       struct pinctrl_state *pins_uhs;
> > +       struct delayed_work req_timeout;
> > +       int irq;                /* host interrupt */
> > +
> > +       struct clk *src_clk;    /* msdc source clock */
> > +       u32 mclk;               /* mmc subsystem clock */
> > +       u32 hclk;               /* host clock speed */
> > +       u32 sclk;               /* SD/MS clock speed */
> > +       bool ddr;
> > +};
> > +
> > +static void sdr_set_bits(void __iomem *reg, u32 bs)
> > +{
> > +       u32 val = readl(reg);
> > +
> > +       val |= bs;
> > +       writel(val, reg);
> > +}
> > +
> > +static void sdr_clr_bits(void __iomem *reg, u32 bs)
> > +{
> > +       u32 val = readl(reg);
> > +
> > +       val &= ~(u32)bs;
> > +       writel(val, reg);
> > +}
> > +
> > +static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
> > +{
> > +       unsigned int tv = readl(reg);
> > +
> > +       tv &= ~field;
> > +       tv |= ((val) << (ffs((unsigned int)field) - 1));
> > +       writel(tv, reg);
> > +}
> 
> A common thought for all the three above functions:
> 
> Have you considered using a cache variable for those registers that
> often gets updated? In that way you would have to read the register
> value every time when you want to write to it. It should improve
> performance a bit.
> 
These register can be modified by the MSDC hw, cannot cache it.
> > +
> > +static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
> > +{
> > +       unsigned int tv = readl(reg);
> > +
> > +       *val = ((tv & field) >> (ffs((unsigned int)field) - 1));
> > +}
> > +
> > +static void msdc_reset_hw(struct msdc_host *host)
> > +{
> > +       u32 val;
> > +
> > +       sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
> > +       while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
> > +               cpu_relax();
> > +
> > +       sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
> > +       while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
> > +               cpu_relax();
> > +
> > +       val = readl(host->base + MSDC_INT);
> > +       writel(val, host->base + MSDC_INT);
> > +}
> > +
> > +static void msdc_cmd_next(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd);
> 
> Please investigate whether you can move around the code to prevent
> this static declaration of the function.
> 
It is hard to do it, because the first cmd may be CMD23, and do the next is send the mrq->cmd, so, there is a loop here, at least on method need do static declaration,
> > +
> > +static inline u32 msdc_data_ints_mask(struct msdc_host *host)
> > +{
> > +       u32 wints =
> > +               /* data xfer */
> > +               MSDC_INTEN_XFER_COMPL |
> > +               MSDC_INTEN_DATTMO |
> > +               MSDC_INTEN_DATCRCERR |
> > +               /* DMA events */
> > +               MSDC_INTEN_DMA_BDCSERR |
> > +               MSDC_INTEN_DMA_GPDCSERR |
> > +               MSDC_INTEN_DMA_PROTECT;
> > +
> > +       return wints;
> > +}
> 
> This should be a static variable instead of a function.
> 
Ok, will fix at next revision.
> > +
> > +static u8 msdc_dma_calcs(u8 *buf, u32 len)
> > +{
> > +       u32 i, sum = 0;
> > +
> > +       for (i = 0; i < len; i++)
> > +               sum += buf[i];
> > +       return 0xff - (u8) sum;
> > +}
> > +
> > +static inline void msdc_dma_setup(struct msdc_host *host, struct
> msdc_dma *dma,
> > +               struct mmc_data *data)
> > +{
> > +       u32 sglen, j;
> > +       u32 dma_address, dma_len;
> > +       struct scatterlist *sg;
> > +       struct mt_gpdma_desc *gpd;
> > +       struct mt_bdma_desc *bd;
> > +
> > +       sglen = data->sg_len;
> > +       sg = data->sg;
> > +
> > +       gpd = dma->gpd;
> > +       bd = dma->bd;
> > +
> > +       /* modify gpd */
> > +       gpd->first_u32 |= GPDMA_DESC_HWO;
> > +       gpd->first_u32 |= GPDMA_DESC_BDP;
> > +       /* need to clear first. use these bits to calc checksum */
> > +       gpd->first_u32 &= ~GPDMA_DESC_CHECKSUM;
> > +       gpd->first_u32 |= msdc_dma_calcs((u8 *) gpd, 16) << 8;
> > +
> > +       /* modify bd */
> > +       for (j = 0; j < sglen; j++) {
> > +               dma_address = sg_dma_address(sg);
> > +               dma_len = sg_dma_len(sg);
> > +
> > +               /* init bd */
> > +               bd[j].first_u32 &= ~BDMA_DESC_BLKPAD;
> > +               bd[j].first_u32 &= ~BDMA_DESC_DWPAD;
> > +               bd[j].ptr = (u32)dma_address;
> > +               bd[j].second_u32 &= ~BDMA_DESC_BUFLEN;
> > +               bd[j].second_u32 |= (dma_len & BDMA_DESC_BUFLEN);
> > +
> > +               if (j == sglen - 1) /* the last bd */
> > +                       bd[j].first_u32 |= BDMA_DESC_EOL;
> > +               else
> > +                       bd[j].first_u32 &= ~BDMA_DESC_EOL;
> > +
> > +               /* checksume need to clear first */
> > +               bd[j].first_u32 &= ~BDMA_DESC_CHECKSUM;
> > +               bd[j].first_u32 |= msdc_dma_calcs((u8 *)(&bd[j]), 16) <<
> 8;
> > +               sg++;
> > +       }
> > +
> > +       sdr_set_field(host->base + MSDC_DMA_CFG,
> MSDC_DMA_CFG_DECSEN, 1);
> > +       sdr_set_field(host->base + MSDC_DMA_CTRL,
> MSDC_DMA_CTRL_BRUSTSZ,
> > +                       MSDC_BURST_64B);
> > +       sdr_set_field(host->base + MSDC_DMA_CTRL,
> MSDC_DMA_CTRL_MODE, 1);
> > +
> > +       writel((u32)dma->gpd_addr, host->base + MSDC_DMA_SA);
> > +}
> > +
> > +static void msdc_prepare_data(struct msdc_host *host, struct
> mmc_request *mrq)
> > +{
> > +       struct mmc_data *data = mrq->data;
> > +
> > +       if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
> > +               bool read = (data->flags & MMC_DATA_READ) != 0;
> > +
> > +               data->host_cookie |= MSDC_PREPARE_FLAG;
> > +               dma_map_sg(host->dev, data->sg, data->sg_len,
> > +                          read ? DMA_FROM_DEVICE :
> DMA_TO_DEVICE);
> > +       }
> > +}
> > +
> > +static void msdc_unprepare_data(struct msdc_host *host, struct
> mmc_request *mrq)
> > +{
> > +       struct mmc_data *data = mrq->data;
> > +
> > +       if (data->host_cookie & MSDC_ASYNC_FLAG)
> > +               return;
> > +
> > +       if ((data->host_cookie & MSDC_PREPARE_FLAG)) {
> > +               bool read = (data->flags & MMC_DATA_READ) != 0;
> > +
> > +               dma_unmap_sg(host->dev, data->sg, data->sg_len,
> > +                            read ? DMA_FROM_DEVICE :
> DMA_TO_DEVICE);
> > +               data->host_cookie &= ~MSDC_PREPARE_FLAG;
> > +       }
> > +}
> > +
> > +/* clock control primitives */
> > +static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
> > +{
> > +       u32 timeout, clk_ns;
> > +       u32 mode = 0;
> > +
> > +       host->timeout_ns = ns;
> > +       host->timeout_clks = clks;
> > +       if (host->sclk == 0) {
> > +               timeout = 0;
> > +       } else {
> > +               clk_ns  = 1000000000UL / host->sclk;
> > +               timeout = (ns + clk_ns - 1) / clk_ns + clks;
> > +               /* in 1048576 sclk cycle unit */
> > +               timeout = (timeout + (1 << 20) - 1) >> 20;
> > +               sdr_get_field(host->base + MSDC_CFG,
> MSDC_CFG_CKMOD, &mode);
> > +               /*DDR mode will double the clk cycles for data timeout */
> 
> How do you know you will be using DDR at this point? Don't you need to
> check for that?
> 
The MSDC_CFG_CKMODE can show current mode(DDR or SDR).

> > +               timeout = mode >= 2 ? timeout * 2 : timeout;
> > +               timeout = timeout > 1 ? timeout - 1 : 0;
> > +               timeout = timeout > 255 ? 255 : timeout;
> > +       }
> > +       sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
> > +}
> > +
> > +static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
> > +{
> > +       u32 mode;
> > +       u32 flags;
> > +       u32 div;
> > +       u32 sclk;
> > +       u32 hclk = host->hclk;
> > +
> > +       if (!hz) {
> > +               dev_err(host->dev, "set mclk to 0\n");
> > +               host->mclk = 0;
> 
> This isn't supposed to be treated as an error. The mmc core expect the
> host to gate the clock when the rate is zero.
> 
> This is also needed when dealing with I/O voltage switch for UHS cards.
> 
Yes, will only set the host mode to MS(which will stop the bus clock) and give a dev_dbg message.

> > +               msdc_reset_hw(host);
> > +               return;
> > +       }
> > +
> > +       flags = readl(host->base + MSDC_INTEN);
> > +       sdr_clr_bits(host->base + MSDC_INTEN, flags);
> > +
> > +       if (ddr) { /* may need to modify later */
> > +               mode = 0x2; /* ddr mode and use divisor */
> > +               if (hz >= (hclk >> 2)) {
> > +                       div = 0; /* mean div = 1/4 */
> > +                       sclk = hclk >> 2; /* sclk = clk / 4 */
> > +               } else {
> > +                       div = (hclk + ((hz << 2) - 1)) / (hz << 2);
> > +                       sclk = (hclk >> 2) / div;
> > +                       div = (div >> 1);
> > +               }
> > +       } else if (hz >= hclk) {
> > +               mode = 0x1; /* no divisor */
> > +               div = 0;
> > +               sclk = hclk;
> > +       } else {
> > +               mode = 0x0; /* use divisor */
> > +               if (hz >= (hclk >> 1)) {
> > +                       div = 0; /* mean div = 1/2 */
> > +                       sclk = hclk >> 1; /* sclk = clk / 2 */
> > +               } else {
> > +                       div = (hclk + ((hz << 2) - 1)) / (hz << 2);
> > +                       sclk = (hclk >> 2) / div;
> > +               }
> > +       }
> > +
> > +       sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD |
> MSDC_CFG_CKDIV,
> > +                       (mode << 8) | (div % 0xff));
> > +       while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
> > +               cpu_relax();
> > +
> > +       host->sclk = sclk;
> > +       host->mclk = hz;
> > +       host->ddr = ddr;
> > +       /* need because clk changed. */
> > +       msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
> > +       sdr_set_bits(host->base + MSDC_INTEN, flags);
> > +
> > +       dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);
> > +}
> > +
> > +static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd)
> > +{
> > +       u32 resp;
> > +
> > +       switch (mmc_resp_type(cmd)) {
> > +               /* Actually, R1, R5, R6, R7 are the same */
> > +       case MMC_RSP_R1:
> > +               resp = 1;
> > +               break;
> > +       case MMC_RSP_R1B:
> > +               resp = 7;
> > +               break;
> > +       case MMC_RSP_R2:
> > +               resp = 2;
> > +               break;
> > +       case MMC_RSP_R3:
> > +               resp = 3;
> > +               break;
> > +       case MMC_RSP_NONE:
> > +       default:
> > +               resp = 0;
> > +               break;
> > +       }
> > +
> > +       return resp;
> > +}
> 
> I would rather see that the above function return hex values instead
> of decimals.
> 
Sure. Will fix it.
> > +
> > +static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd)
> > +{
> > +       /* rawcmd :
> > +        * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
> > +        * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 |
> opcode
> > +        */
> > +       u32 opcode = cmd->opcode;
> > +       u32 resp = msdc_cmd_find_resp(host, mrq, cmd);
> > +       u32 rawcmd = (opcode & 0x3f) | ((resp & 7) << 7);
> 
> Would be nice to maintain consistency and thus stick to use hex values
> for bitwise OR/AND.
> 
OK, fix it at next revision.
> > +
> > +       host->cmd_rsp = resp;
> > +
> > +       if ((opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)
> -1) ||
> > +                       opcode == MMC_STOP_TRANSMISSION)
> > +               rawcmd |= (1 << 14);
> > +       else if (opcode == SD_SWITCH_VOLTAGE)
> > +               rawcmd |= (1 << 30);
> > +       else if ((opcode == SD_APP_SEND_SCR) ||
> > +                       (opcode == SD_APP_SEND_NUM_WR_BLKS) ||
> > +                       (opcode == SD_SWITCH &&
> > +                       (mmc_cmd_type(cmd) == MMC_CMD_ADTC))
> ||
> > +                       (opcode == SD_APP_SD_STATUS &&
> > +                       (mmc_cmd_type(cmd) == MMC_CMD_ADTC))
> ||
> > +                       (opcode == MMC_SEND_EXT_CSD &&
> > +                       (mmc_cmd_type(cmd) == MMC_CMD_ADTC)))
> > +               rawcmd |= (1 << 11);
> > +
> > +       if (cmd->data) {
> > +               struct mmc_data *data = cmd->data;
> > +
> > +               if (mmc_op_multi(opcode)) {
> > +                       if (mmc_card_mmc(host->mmc->card) &&
> mrq->sbc &&
> > +                                       !(mrq->sbc->arg &
> 0xFFFF0000))
> > +                               rawcmd |= 2 << 28; /* AutoCMD23 */
> 
> Hex values and lower-case letters in the hex values, to keep consistency...
> 
> I will stop commenting on this from now on, since I realize it applies
> to the complete code. Please go through the code and fix this.
Ok, will fix it.
> 
> > +               }
> > +
> > +               rawcmd |= ((data->blksz & 0xFFF) << 16);
> > +               if (data->flags & MMC_DATA_WRITE)
> > +                       rawcmd |= (1 << 13);
> > +               if (data->blocks > 1)
> > +                       rawcmd |= (2 << 11);
> > +               else
> > +                       rawcmd |= (1 << 11);
> > +               /* Always use dma mode */
> > +               sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO);
> > +
> > +               if (((host->timeout_ns != data->timeout_ns) ||
> > +                               (host->timeout_clks !=
> data->timeout_clks))) {
> > +                       msdc_set_timeout(host, data->timeout_ns,
> > +                                       data->timeout_clks);
> > +               }
> > +
> > +               writel(data->blocks, host->base + SDC_BLK_NUM);
> > +       }
> > +       return rawcmd;
> > +}
> > +
> > +static void msdc_start_data(struct msdc_host *host, struct mmc_request
> *mrq,
> > +                           struct mmc_command *cmd, struct
> mmc_data *data)
> > +{
> > +       bool read;
> > +       unsigned long flags;
> > +       u32 wints;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       if (!host->data) {
> > +               host->data = data;
> > +       } else {
> > +               dev_err(host->dev, "%s: CMD%d [%d blocks] is active",
> > +                               __func__, host->mrq->cmd->opcode,
> > +                               host->data->blocks);
> > +               dev_err(host->dev, "but new CMD%d [%d blocks]
> started\n",
> > +                       cmd->opcode, data->blocks);
> > +       }
> > +       spin_unlock_irqrestore(&host->lock, flags);
> 
> How about replacing the above error check with a single WARN_ON() instead?
> 
> > +       read = (data->flags & MMC_DATA_READ) != 0;
> 
> Simplify to:
> 
> read = data->flags & MMC_DATA_READ;
OK, will fix it at next revision,
> 
> > +       data->error = 0;
> 
> You shouldn't need to reset that, handle by the mmc core.
> 
> > +       if (data->stop)
> > +               data->stop->error = 0;
> 
> You shouldn't need to reset that, handle by the mmc core.
> 
OK, will fix them at next revision,
> > +
> > +       mod_delayed_work(system_wq, &host->req_timeout,
> DAT_TIMEOUT);
> > +       msdc_dma_setup(host, &host->dma, data);
> > +       wints = msdc_data_ints_mask(host);
> > +       sdr_set_bits(host->base + MSDC_INTEN, wints);
> > +       mb(); /* wait for pending IO to finish */
> > +       sdr_set_field(host->base + MSDC_DMA_CTRL,
> MSDC_DMA_CTRL_START, 1);
> > +       dev_dbg(host->dev, "DMA start\n");
> > +       dev_dbg(host->dev, "%s: cmd=%d DMA data: %d blocks;
> read=%d\n",
> > +                       __func__, cmd->opcode, data->blocks, read);
> > +}
> > +
> > +static int msdc_auto_cmd_done(struct msdc_host *host, int events,
> > +               struct mmc_command *cmd)
> > +{
> > +       u32 *rsp = cmd->resp;
> > +
> > +       rsp[0] = readl(host->base + SDC_ACMD_RESP);
> > +
> > +       if (events & MSDC_INT_ACMDRDY) {
> > +               cmd->error = 0;
> > +       } else {
> > +               msdc_reset_hw(host);
> > +               if (events & MSDC_INT_ACMDCRCERR) {
> > +                       cmd->error = (unsigned int) -EILSEQ;
> > +                       host->error |= REQ_STOP_EIO;
> > +               } else if (events & MSDC_INT_ACMDTMO) {
> > +                       cmd->error = (unsigned int) -ETIMEDOUT;
> > +                       host->error |= REQ_STOP_TMO;
> > +               }
> > +               dev_err(host->dev,
> > +                       "%s: AUTO_CMD%d arg=%08X; rsp %08X;
> cmd_error=%d\n",
> > +                       __func__, cmd->opcode, cmd->arg, rsp[0],
> > +                       (int)cmd->error);
> > +       }
> > +       return (int)(cmd->error);
> 
> This is silly. The struct mmc_command|data->error field should be of
> type int and not unsigned int, which isn't the case currently.
> 
> Host driver shouldn't need to deal with this casting. I have just sent
> a patch to change "error" to an int. Please align to that change, in
> all places where you use the "error" field.
> 
OK, will fix it at next revision,
> > +}
> > +
> > +static void msdc_track_cmd_data(struct msdc_host *host,
> > +                               struct mmc_command *cmd, struct
> mmc_data *data)
> > +{
> > +       if (host->error)
> > +               dev_dbg(host->dev, "%s: cmd=%d arg=%08X;
> host->error=0x%08X\n",
> > +                       __func__, cmd->opcode, cmd->arg,
> host->error);
> > +}
> > +
> > +static void msdc_request_done(struct msdc_host *host, struct
> mmc_request *mrq)
> > +{
> > +       unsigned long flags;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       cancel_delayed_work(&host->req_timeout);
> 
> This looks racy.
> 
> Don't you need a cancel_delayed_work_sync() from somewhere, to be sure
> that work isn't preemted after the "host->mrq" has been reset here? Or
> maybe there is another way!? Of course that can't be done with the
> spin_locks held, but I asume you get my point.
Yes, I get your point, actually, we set a 5s timeout for each request, and, if the work already pending(means that some error happens), we do not wait it,
And the work will set the event to timeout and return,
So, maybe a good solution is that need check the return value of the cancel_delayed_work(), if it is pending, directly return, and do not set the host->mrq to 0 to avoid the race condition,
> 
> > +       host->mrq = NULL;
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +
> > +       msdc_track_cmd_data(host, mrq->cmd, mrq->data);
> > +       if (mrq->data)
> > +               msdc_unprepare_data(host, mrq);
> > +       mmc_request_done(host->mmc, mrq);
> > +}
> > +
> > +/* returns true if command is fully handled; returns false otherwise */
> > +static bool msdc_cmd_done(struct msdc_host *host, int events,
> > +                         struct mmc_request *mrq, struct
> mmc_command *cmd)
> > +{
> > +       bool done = false;
> > +       bool sbc_error;
> > +       unsigned long flags;
> > +       u32 *rsp = cmd->resp;
> > +
> > +       if (mrq->sbc && cmd == mrq->cmd &&
> > +                       (events & (MSDC_INT_ACMDRDY |
> MSDC_INT_ACMDCRCERR
> > +                                  | MSDC_INT_ACMDTMO)))
> > +               msdc_auto_cmd_done(host, events, mrq->sbc);
> > +
> > +       sbc_error = mrq->sbc && mrq->sbc->error;
> > +
> > +       if (!sbc_error && !(events & (MSDC_INT_CMDRDY
> > +                                       | MSDC_INT_RSPCRCERR
> > +                                       | MSDC_INT_CMDTMO)))
> > +               return done;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       done = !host->cmd;
> > +       host->cmd = NULL;
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +
> > +       if (done)
> > +               return true;
> > +
> > +       sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
> > +                       MSDC_INTEN_RSPCRCERR |
> MSDC_INTEN_CMDTMO |
> > +                       MSDC_INTEN_ACMDRDY |
> MSDC_INTEN_ACMDCRCERR |
> > +                       MSDC_INTEN_ACMDTMO);
> > +       writel(cmd->arg, host->base + SDC_ARG);
> > +
> > +       switch (host->cmd_rsp) {
> > +       case 0:
> > +               break;
> > +       case 2:
> > +               rsp[0] = readl(host->base + SDC_RESP3);
> > +               rsp[1] = readl(host->base + SDC_RESP2);
> > +               rsp[2] = readl(host->base + SDC_RESP1);
> > +               rsp[3] = readl(host->base + SDC_RESP0);
> > +               break;
> > +       default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
> > +               rsp[0] = readl(host->base + SDC_RESP0);
> > +               break;
> > +       }
> > +       if (!sbc_error && !(events & MSDC_INT_CMDRDY)) {
> > +               msdc_reset_hw(host);
> > +               if (events & MSDC_INT_RSPCRCERR) {
> > +                       cmd->error = (unsigned int) -EILSEQ;
> > +                       host->error |= REQ_CMD_EIO;
> > +               } else if (events & MSDC_INT_CMDTMO) {
> > +                       cmd->error = (unsigned int) -ETIMEDOUT;
> > +                       host->error |= REQ_CMD_TMO;
> > +               }
> > +       }
> > +       if (cmd->error)
> > +               dev_dbg(host->dev,
> > +                               "%s: cmd=%d arg=%08X; rsp %08X;
> cmd_error=%d\n",
> > +                               __func__, cmd->opcode, cmd->arg,
> rsp[0],
> > +                               (int)cmd->error);
> > +
> > +       msdc_cmd_next(host, mrq, cmd);
> > +       done = true;
> > +       return done;
> > +}
> > +
> > +static inline bool msdc_cmd_is_ready(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd)
> > +{
> > +       unsigned long tmo = jiffies + msecs_to_jiffies(20);
> > +
> > +       while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY)
> > +                       && time_before(jiffies, tmo))
> > +               continue;
> > +
> > +       if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
> > +               dev_err(host->dev, "CMD bus busy detected\n");
> > +               host->error |= REQ_CMD_BUSY;
> > +               msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
> > +               return false;
> > +       }
> > +
> > +       if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
> > +               /* R1B or with data, should check SDCBUSY */
> > +               while (readl(host->base + SDC_STS) &
> SDC_STS_SDCBUSY)
> > +                       cpu_relax();
> > +       }
> > +       return true;
> > +}
> > +
> > +static void msdc_start_command(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd)
> > +{
> > +       u32 rawcmd;
> > +       unsigned long flags;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       if (host->cmd) {
> > +               dev_err(host->dev, "%s: CMD%d is active, but new
> CMD%d is sent\n",
> > +                               __func__, host->cmd->opcode,
> cmd->opcode);
> > +       } else {
> > +               host->cmd = cmd;
> > +       }
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +
> 
> How about replacing the above error check with a single WARN_ON() instead?
> 
Sure, it is good, will fix it at next revision,
> > +       if (!msdc_cmd_is_ready(host, mrq, cmd))
> > +               return;
> > +
> > +       if ((readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >>
> 16
> > +               || (readl(host->base + MSDC_FIFOCS) &
> MSDC_FIFOCS_RXCNT)) {
> > +               dev_err(host->dev, "TX/RX FIFO non-empty before start of
> IO. Reset\n");
> > +               msdc_reset_hw(host);
> > +       }
> > +
> > +       cmd->error = 0;
> > +       rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
> > +       mod_delayed_work(system_wq, &host->req_timeout,
> DAT_TIMEOUT);
> > +
> > +       sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
> > +                       MSDC_INTEN_RSPCRCERR |
> MSDC_INTEN_CMDTMO |
> > +                       MSDC_INTEN_ACMDRDY |
> MSDC_INTEN_ACMDCRCERR |
> > +                       MSDC_INTEN_ACMDTMO);
> > +       writel(cmd->arg, host->base + SDC_ARG);
> > +       writel(rawcmd, host->base + SDC_CMD);
> > +}
> > +
> > +static void msdc_cmd_next(struct msdc_host *host,
> > +               struct mmc_request *mrq, struct mmc_command *cmd)
> > +{
> > +       if (cmd->error || (mrq->sbc && mrq->sbc->error))
> > +               msdc_request_done(host, mrq);
> > +       else if (cmd == mrq->sbc)
> > +               msdc_start_command(host, mrq, mrq->cmd);
> > +       else if (!cmd->data)
> > +               msdc_request_done(host, mrq);
> > +       else
> > +               msdc_start_data(host, mrq, cmd, cmd->data);
> > +}
> > +
> > +static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request
> *mrq)
> > +{
> > +       unsigned long flags;
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +
> > +       host->error = 0;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       if (!host->mrq) {
> > +               host->mrq = mrq;
> > +       } else {
> > +               dev_err(host->dev,
> > +                       "%s: req [CMD%d] is active, new req [CMD%d]
> is sent\n",
> > +                       __func__, host->mrq->cmd->opcode,
> mrq->cmd->opcode);
> > +       }
> > +       spin_unlock_irqrestore(&host->lock, flags);
> 
> How about replacing the above error check with a single WARN_ON() instead?
OK, will fix it at next revision.
> 
> > +
> > +       if (mrq->data)
> > +               msdc_prepare_data(host, mrq);
> > +
> > +       /* if SBC is required, we have HW option and SW option.
> > +        * if HW option is enabled, and SBC does not have "special" flags,
> > +        * use HW option,  otherwise use SW option
> > +        */
> > +       if (mrq->sbc && (!mmc_card_mmc(mmc->card) ||
> > +           (mrq->sbc->arg & 0xFFFF0000)))
> > +               msdc_start_command(host, mrq, mrq->sbc);
> > +       else
> > +               msdc_start_command(host, mrq, mrq->cmd);
> > +}
> > +
> > +static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request
> *mrq,
> > +               bool is_first_req)
> > +{
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +       struct mmc_data *data = mrq->data;
> > +
> > +       if (!data)
> > +               return;
> > +
> > +       msdc_prepare_data(host, mrq);
> > +       data->host_cookie |= MSDC_ASYNC_FLAG;
> > +}
> > +
> > +static void msdc_post_req(struct mmc_host *mmc, struct mmc_request
> *mrq,
> > +               int err)
> > +{
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +       struct mmc_data *data;
> > +
> > +       data = mrq->data;
> > +       if (!data)
> > +               return;
> > +       if (data->host_cookie) {
> > +               data->host_cookie &= ~MSDC_ASYNC_FLAG;
> > +               msdc_unprepare_data(host, mrq);
> > +       }
> > +}
> > +
> > +static void msdc_data_xfer_next(struct msdc_host *host,
> > +                               struct mmc_request *mrq, struct
> mmc_data *data)
> > +{
> > +       if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop
> && !mrq->stop->error &&
> > +                       (!data->bytes_xfered || !mrq->sbc))
> > +               msdc_start_command(host, mrq, mrq->stop);
> > +       else
> > +               msdc_request_done(host, mrq);
> > +}
> > +
> > +static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
> > +                               struct mmc_request *mrq, struct
> mmc_data *data)
> > +{
> > +       struct mmc_command *stop = data->stop;
> > +       unsigned long flags;
> > +       bool done;
> > +       u32 wints;
> > +
> > +       bool check_data = (events &
> > +           (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR |
> MSDC_INT_DATTMO
> > +            | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
> > +            | MSDC_INT_DMA_PROTECT));
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       done = !host->data;
> > +       if (check_data)
> > +               host->data = NULL;
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +
> > +       if (done)
> > +               return true;
> > +
> > +       if (check_data || (stop && stop->error)) {
> > +               dev_dbg(host->dev, "DMA status: 0x%8X\n",
> > +                               readl(host->base +
> MSDC_DMA_CFG));
> > +               sdr_set_field(host->base + MSDC_DMA_CTRL,
> MSDC_DMA_CTRL_STOP,
> > +                               1);
> > +               while (readl(host->base + MSDC_DMA_CFG) &
> MSDC_DMA_CFG_STS)
> > +                       ;
> > +               mb(); /* wait for pending IO to finish */
> > +               wints = msdc_data_ints_mask(host);
> > +               sdr_clr_bits(host->base + MSDC_INTEN, wints);
> > +               dev_dbg(host->dev, "DMA stop\n");
> > +
> > +               if ((events & MSDC_INT_XFER_COMPL) && (!stop
> || !stop->error)) {
> > +                       data->bytes_xfered = data->blocks *
> data->blksz;
> > +               } else {
> > +                       dev_err(host->dev, "interrupt events: %x\n",
> events);
> > +                       msdc_reset_hw(host);
> > +                       host->error |= REQ_DAT_ERR;
> > +                       data->bytes_xfered = 0;
> > +
> > +                       if (events & MSDC_INT_DATTMO)
> > +                               data->error = (unsigned int)
> -ETIMEDOUT;
> > +
> > +                       dev_err(host->dev, "%s: cmd=%d; blocks=%d",
> > +                               __func__, mrq->cmd->opcode,
> data->blocks);
> > +                       dev_err(host->dev, "data_error=%d
> xfer_size=%d\n",
> > +                                       (int)data->error,
> data->bytes_xfered);
> > +               }
> > +
> > +               msdc_data_xfer_next(host, mrq, data);
> > +               done = true;
> > +       }
> > +       return done;
> > +}
> > +
> > +static void msdc_set_buswidth(struct msdc_host *host, u32 width)
> > +{
> > +       u32 val = readl(host->base + SDC_CFG);
> > +
> > +       val &= ~SDC_CFG_BUSWIDTH;
> > +
> > +       switch (width) {
> > +       default:
> > +       case MMC_BUS_WIDTH_1:
> > +               val |= (MSDC_BUS_1BITS << 16);
> > +               break;
> > +       case MMC_BUS_WIDTH_4:
> > +               val |= (MSDC_BUS_4BITS << 16);
> > +               break;
> > +       case MMC_BUS_WIDTH_8:
> > +               val |= (MSDC_BUS_8BITS << 16);
> > +               break;
> > +       }
> > +
> > +       writel(val, host->base + SDC_CFG);
> > +       dev_dbg(host->dev, "Bus Width = %d", width);
> > +}
> > +
> > +static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios
> *ios)
> > +{
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +       int min_uv, max_uv;
> > +       int ret = 0;
> > +
> > +       if (!IS_ERR(mmc->supply.vqmmc)) {
> > +
> > +               if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
> > +                       min_uv = 3300000;
> > +                       max_uv = 3300000;
> > +               } else if (ios->signal_voltage ==
> MMC_SIGNAL_VOLTAGE_180) {
> > +                       min_uv = 1800000;
> > +                       max_uv = 1800000;
> > +               } else {
> > +                       dev_err(host->dev, "Unsupported signal
> voltage!\n");
> > +                       return -EINVAL;
> > +               }
> > +
> > +               ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv,
> max_uv);
> > +               if (ret) {
> > +                       dev_err(host->dev,
> > +                                       "Regulator set error %d: %d
> - %d\n",
> > +                                       ret, min_uv, max_uv);
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static void msdc_request_timeout(struct work_struct *work)
> > +{
> > +       struct msdc_host *host = container_of(work, struct msdc_host,
> > +                       req_timeout.work);
> > +       unsigned long flags;
> > +       struct mmc_request *mrq;
> > +       struct mmc_command *cmd;
> > +       struct mmc_data *data;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       mrq = ACCESS_ONCE(host->mrq);
> > +       cmd = ACCESS_ONCE(host->cmd);
> > +       data = ACCESS_ONCE(host->data);
> 
> Why do you need the ACCESS_ONCE here. Aren't these pointers already
> protected by the spin_lock?
> OK, will remove the ACCESS_ONCE.
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +
> > +       /* simulate HW timeout status */
> > +       dev_err(host->dev, "%s: aborting cmd/data/mrq\n", __func__);
> > +       if (mrq) {
> > +               dev_err(host->dev, "%s: aborting mrq=%p cmd=%d\n",
> __func__,
> > +                       mrq, mrq->cmd->opcode);
> > +               if (cmd) {
> > +                       dev_err(host->dev, "%s: aborting cmd=%d\n",
> > +                                       __func__, cmd->opcode);
> > +                       msdc_cmd_done(host, MSDC_INT_CMDTMO,
> mrq, cmd);
> > +               } else if (data) {
> > +                       dev_err(host->dev, "%s: abort data: cmd%d; %d
> blocks\n",
> > +                               __func__, mrq->cmd->opcode,
> data->blocks);
> > +                       msdc_data_xfer_done(host,
> MSDC_INT_DATTMO, mrq, data);
> > +               }
> > +       }
> > +}
> > +
> > +static irqreturn_t msdc_irq(int irq, void *dev_id)
> > +{
> > +       struct msdc_host *host = (struct msdc_host *) dev_id;
> > +
> > +       while (true) {
> > +               unsigned long flags;
> > +               struct mmc_request *mrq;
> > +               struct mmc_command *cmd;
> > +               struct mmc_data *data;
> > +               u32 events, event_mask;
> > +
> > +               spin_lock_irqsave(&host->lock, flags);
> > +               events = readl(host->base + MSDC_INT);
> > +               event_mask = readl(host->base + MSDC_INTEN);
> > +               /* clear interrupts */
> > +               writel(events, host->base + MSDC_INT);
> > +
> > +               mrq = ACCESS_ONCE(host->mrq);
> > +               cmd = ACCESS_ONCE(host->cmd);
> > +               data = ACCESS_ONCE(host->data);
> 
> Why do you need the ACCESS_ONCE here. Aren't these pointers already
> protected by the spin_lock?
Will fix it at next revision.
> 
> > +               spin_unlock_irqrestore(&host->lock, flags);
> > +
> > +               if (!(events & event_mask))
> > +                       break;
> > +
> > +               if (!mrq) {
> > +                       dev_err(host->dev,
> > +                               "%s: MRQ=NULL; events=%08X;
> event_mask=%08X\n",
> > +                               __func__, events, event_mask);
> > +                       WARN_ON(1);
> > +                       break;
> > +               }
> > +
> > +               dev_dbg(host->dev, "%s: events=%08X\n", __func__,
> events);
> > +
> > +               if (cmd)
> > +                       msdc_cmd_done(host, events, mrq, cmd);
> > +               else if (data)
> > +                       msdc_data_xfer_done(host, events, mrq,
> data);
> > +       }
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +static void msdc_init_hw(struct msdc_host *host)
> > +{
> > +       u32 val;
> > +       /* Configure to MMC/SD mode */
> > +       sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE,
> MSDC_SDMMC);
> > +
> > +       /* Reset */
> > +       msdc_reset_hw(host);
> > +
> > +       /* Disable card detection */
> > +       sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
> > +
> > +       /* Disable and clear all interrupts */
> > +       writel(0, host->base + MSDC_INTEN);
> > +       val = readl(host->base + MSDC_INT);
> > +       writel(val, host->base + MSDC_INT);
> > +
> > +       writel(0, host->base + MSDC_PAD_TUNE);
> > +       writel(0, host->base + MSDC_IOCON);
> > +       sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL,
> 1);
> > +       writel(0x403c004f, host->base + MSDC_PATCH_BIT);
> > +       sdr_set_field(host->base + MSDC_PATCH_BIT,
> MSDC_CKGEN_MSDC_DLY_SEL, 1);
> > +       writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
> > +       /* Configure to enable SDIO mode.
> > +          it's must otherwise sdio cmd5 failed */
> > +       sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
> > +
> > +       /* disable detect SDIO device interrupt function */
> > +       sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
> > +
> > +       /* Configure to default data timeout */
> > +       sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
> > +       msdc_set_buswidth(host, MMC_BUS_WIDTH_1);
> > +
> > +       dev_dbg(host->dev, "init hardware done!");
> > +}
> > +
> > +static void msdc_deinit_hw(struct msdc_host *host)
> > +{
> > +       u32 val;
> > +
> > +       /* Disable and clear all interrupts */
> > +       writel(0, host->base + MSDC_INTEN);
> > +
> > +       val = readl(host->base + MSDC_INT);
> > +       writel(val, host->base + MSDC_INT);
> > +
> > +       clk_disable(host->src_clk);
> > +       clk_unprepare(host->src_clk);
> 
> Please use clk_disable_unprepare() instead.
> 
OK, will fix it.
> > +}
> > +
> > +/* init gpd and bd list in msdc_drv_probe */
> > +static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma
> *dma)
> > +{
> > +       struct mt_gpdma_desc *gpd = dma->gpd;
> > +       struct mt_bdma_desc *bd = dma->bd;
> > +       int i;
> > +
> > +       memset(gpd, 0, sizeof(struct mt_gpdma_desc) * MAX_GPD_NUM);
> > +       gpd->next = (u32)dma->gpd_addr + sizeof(struct mt_gpdma_desc);
> > +
> > +       gpd->first_u32 |= GPDMA_DESC_BDP; /* hwo, cs, bd pointer */
> > +       gpd->ptr = (u32)dma->bd_addr; /* physical address */
> > +
> > +       memset(bd, 0, sizeof(struct mt_bdma_desc) *
> MAX_BD_PER_GPD);
> > +
> > +       for (i = 0; i < (MAX_BD_PER_GPD - 1); i++)
> > +               bd[i].next = (u32)dma->bd_addr + sizeof(*bd) * (i + 1);
> > +}
> > +
> > +static int timing_is_uhs(unsigned char timing)
> > +{
> > +       if (timing != MMC_TIMING_LEGACY &&
> > +                       timing != MMC_TIMING_MMC_HS &&
> > +                       timing != MMC_TIMING_SD_HS)
> 
> I don't like these assumtions. There may be other cases which isn't
> covered here that isn't UHS.
> 
Actually, I want set different driving by 3.3V/1.8V signal.
So, will replace it ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 and rename the function name.
> > +               return 1;
> > +       return 0;
> > +}
> > +
> > +static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > +{
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +       int ret;
> > +       u32 ddr = 0;
> > +
> > +       if (ios->timing == MMC_TIMING_UHS_DDR50)
> > +               ddr = 1;
> 
> I am not sure if this controller supports eMMC cards as well, but if
> that's the case and it also supports DDR you may also want to check
> for MMC_TIMING_MMC_DDR52.
> 
Will add it at next revision.
> > +
> > +       msdc_set_buswidth(host, ios->bus_width);
> > +
> > +       /* Suspend/Resume will do power off/on */
> > +       switch (ios->power_mode) {
> > +       case MMC_POWER_UP:
> > +               msdc_init_hw(host);
> > +               if (!IS_ERR(mmc->supply.vmmc)) {
> > +                       ret = mmc_regulator_set_ocr(mmc,
> mmc->supply.vmmc,
> > +                                       ios->vdd);
> > +                       if (ret) {
> > +                               dev_err(host->dev, "Failed to set
> vmmc power!\n");
> > +                               return;
> > +                       }
> > +               }
> > +               break;
> > +       case MMC_POWER_ON:
> > +               if (!IS_ERR(mmc->supply.vqmmc)) {
> > +                       ret = regulator_enable(mmc->supply.vqmmc);
> 
> The calls to regulator_enable|disable() for the vqmmc will not be
> balanced properly here. You need a local cache variable like
> "is_enabled" to keep track of this.
> 
OK, will fix it at next revision,
> > +                       if (ret)
> > +                               dev_err(host->dev, "Failed to set
> vqmmc power!\n");
> > +               }
> > +               break;
> > +       case MMC_POWER_OFF:
> > +               if (!IS_ERR(mmc->supply.vmmc))
> > +                       mmc_regulator_set_ocr(mmc,
> mmc->supply.vmmc, 0);
> > +
> > +               if (!IS_ERR(mmc->supply.vqmmc))
> > +                       regulator_disable(mmc->supply.vqmmc);
> > +               break;
> > +       default:
> > +               break;
> > +       }
> > +
> > +       /* Apply different pinctrl settings for different timing */
> > +       if (timing_is_uhs(ios->timing))
> > +               pinctrl_select_state(host->pinctrl, host->pins_uhs);
> > +       else
> > +               pinctrl_select_state(host->pinctrl, host->pins_default);
> > +
> > +       if (host->mclk != ios->clock || host->ddr != ddr)
> > +               msdc_set_mclk(host, ddr, ios->clock);
> > +}
> > +
> > +static struct mmc_host_ops mt_msdc_ops = {
> > +       .post_req = msdc_post_req,
> > +       .pre_req = msdc_pre_req,
> > +       .request = msdc_ops_request,
> > +       .set_ios = msdc_ops_set_ios,
> > +       .start_signal_voltage_switch = msdc_ops_switch_volt,
> > +};
> > +
> > +static int msdc_drv_probe(struct platform_device *pdev)
> > +{
> > +       struct mmc_host *mmc;
> > +       struct msdc_host *host;
> > +       struct resource *res;
> > +       int ret;
> > +
> > +       if (!pdev->dev.of_node) {
> > +               dev_err(&pdev->dev, "No DT found\n");
> > +               return -EINVAL;
> > +       }
> > +       /* Allocate MMC host for this device */
> > +       mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
> > +       if (!mmc)
> > +               return -ENOMEM;
> > +
> > +       host = mmc_priv(mmc);
> > +       ret = mmc_of_parse(mmc);
> > +       if (ret)
> > +               goto host_free;
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       host->base = devm_ioremap_resource(&pdev->dev, res);
> > +       if (IS_ERR(host->base)) {
> > +               ret = PTR_ERR(host->base);
> > +               goto host_free;
> > +       }
> > +
> > +       ret = mmc_regulator_get_supply(mmc);
> > +       if (ret == -EPROBE_DEFER)
> > +               goto host_free;
> > +
> > +       host->src_clk = devm_clk_get(&pdev->dev, "source");
> > +       if (IS_ERR(host->src_clk)) {
> > +               dev_err(&pdev->dev,
> > +                               "Invalid source clock from the device
> tree!\n");
> 
> You can remove this print, it's already handled by the common clk framework.
Ok, will remove it at next revision,
> 
> > +               ret = PTR_ERR(host->src_clk);
> > +               goto host_free;
> > +       }
> > +
> > +       host->irq = platform_get_irq(pdev, 0);
> > +       if (host->irq < 0) {
> > +               ret = -EINVAL;
> > +               goto host_free;
> > +       }
> > +
> > +       host->pinctrl = devm_pinctrl_get(&pdev->dev);
> > +       if (IS_ERR(host->pinctrl)) {
> > +               ret = PTR_ERR(host->pinctrl);
> > +               dev_err(&pdev->dev, "Cannot find pinctrl!\n");
> > +               goto host_free;
> > +       }
> > +
> > +       host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
> > +       if (IS_ERR(host->pins_default)) {
> > +               ret = PTR_ERR(host->pins_default);
> > +               dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
> > +               goto host_free;
> > +       }
> > +
> > +       host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
> > +       if (IS_ERR(host->pins_uhs)) {
> > +               ret = PTR_ERR(host->pins_uhs);
> > +               dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
> > +               goto host_free;
> > +       }
> > +
> > +       host->dev = &pdev->dev;
> > +       host->mmc = mmc;
> > +       /* Set host parameters to mmc */
> > +       mmc->ops = &mt_msdc_ops;
> > +       mmc->f_min = 260000;
> 
> Doesn't f_min depend on some internal divider algorithm and the clock
> rate? So, then it should maybe be calculated instead of fixed?
> 
Yes, the f_min is the source_clock / (4 * 255);
> > +       mmc->ocr_avail = MMC_VDD_30_31 | MMC_VDD_31_32 |
> MMC_VDD_32_33;
> 
> "ocr_avail" should be fetched from the vmmc regulator, when you invoke
> mmc_regulator_get_supply() above.
Yes, I also want to remove it, but, Not all devices use regulator, our SDIO device which connected on MSDC3, it's power is controlled by gpio.
This because the regulator of the PMU is not enough.
> 
> > +
> > +       mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
> > +       /* MMC core transfer sizes tunable parameters */
> > +       mmc->max_segs = MAX_BD_NUM;
> > +       mmc->max_seg_size = 64 * 1024;
> > +       mmc->max_blk_size = 2048;
> > +       mmc->max_req_size = 512 * 1024;
> > +       mmc->max_blk_count = mmc->max_req_size;
> > +
> > +       host->hclk = clk_get_rate(host->src_clk);
> > +       host->timeout_clks = 3 * 1048576;
> > +       host->dma.gpd = dma_alloc_coherent(&pdev->dev,
> > +                               MAX_GPD_NUM * sizeof(struct
> mt_gpdma_desc),
> > +                               &host->dma.gpd_addr,
> GFP_KERNEL);
> > +       host->dma.bd = dma_alloc_coherent(&pdev->dev,
> > +                               MAX_BD_NUM * sizeof(struct
> mt_bdma_desc),
> > +                               &host->dma.bd_addr, GFP_KERNEL);
> > +       if ((!host->dma.gpd) || (!host->dma.bd)) {
> > +               ret = -ENOMEM;
> > +               goto release_mem;
> > +       }
> > +       msdc_init_gpd_bd(host, &host->dma);
> > +       INIT_DELAYED_WORK(&host->req_timeout,
> msdc_request_timeout);
> > +       spin_lock_init(&host->lock);
> > +
> > +       platform_set_drvdata(pdev, mmc);
> > +       clk_prepare(host->src_clk);
> 
> This should be clk_prepare_enable().
> 
I will remove the clk_prepare here and use clk_prepare_enable() at msdc_ungate_clock();
> > +
> > +       ret = devm_request_irq(&pdev->dev, (unsigned int) host->irq,
> msdc_irq,
> > +               IRQF_TRIGGER_LOW | IRQF_ONESHOT, pdev->name,
> host);
> > +       if (ret)
> > +               goto release;
> > +
> > +       ret = mmc_add_host(mmc);
> > +       if (ret)
> > +               goto release;
> > +
> > +       return 0;
> > +
> > +release:
> > +       platform_set_drvdata(pdev, NULL);
> > +       msdc_deinit_hw(host);
> > +release_mem:
> > +       if (host->dma.gpd)
> > +               dma_free_coherent(&pdev->dev,
> > +                       MAX_GPD_NUM * sizeof(struct
> mt_gpdma_desc),
> > +                       host->dma.gpd, host->dma.gpd_addr);
> > +       if (host->dma.bd)
> > +               dma_free_coherent(&pdev->dev,
> > +                       MAX_BD_NUM * sizeof(struct mt_bdma_desc),
> > +                       host->dma.bd, host->dma.bd_addr);
> > +host_free:
> > +       mmc_free_host(mmc);
> > +
> > +       return ret;
> > +}
> > +
> > +static int msdc_drv_remove(struct platform_device *pdev)
> > +{
> > +       struct mmc_host *mmc;
> > +       struct msdc_host *host;
> > +
> > +       mmc = platform_get_drvdata(pdev);
> > +       host = mmc_priv(mmc);
> > +
> > +       platform_set_drvdata(pdev, NULL);
> > +       mmc_remove_host(host->mmc);
> > +       msdc_deinit_hw(host);
> > +
> > +       dma_free_coherent(&pdev->dev,
> > +                       MAX_GPD_NUM * sizeof(struct
> mt_gpdma_desc),
> > +                       host->dma.gpd, host->dma.gpd_addr);
> > +       dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct
> mt_bdma_desc),
> > +                       host->dma.bd, host->dma.bd_addr);
> > +
> > +       mmc_free_host(host->mmc);
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct of_device_id msdc_of_ids[] = {
> > +       {   .compatible = "mediatek,mt8135-mmc", },
> > +       {}
> > +};
> > +
> > +static struct platform_driver mt_msdc_driver = {
> > +       .probe = msdc_drv_probe,
> > +       .remove = msdc_drv_remove,
> > +       .driver = {
> > +               .name = "mtk-msdc",
> > +               .of_match_table = msdc_of_ids,
> > +       },
> > +};
> > +
> > +module_platform_driver(mt_msdc_driver);
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("MediaTek SD/MMC Card Driver");
> > --
> > 1.8.1.1.dirty
> >
> 
> Kind regards
> Uffe

************* Email Confidentiality Notice ********************
The information contained in this e-mail message (including any 
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be 
conveyed only to the designated recipient(s). Any use, dissemination, 
distribution, printing, retaining or copying of this e-mail (including its 
attachments) by unintended recipient(s) is strictly prohibited and may 
be unlawful. If you are not an intended recipient of this e-mail, or believe 
that you have received this e-mail in error, please notify the sender 
immediately (by replying to this e-mail), delete any and all copies of 
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!

From Chaotian.Jing at mediatek.com  Fri Apr  3 01:27:45 2015
From: Chaotian.Jing at mediatek.com (=?utf-8?B?Q2hhb3RpYW4gSmluZyAo5LqV5pyd5aSpKQ==?=)
Date: Fri, 3 Apr 2015 08:27:45 +0000
Subject: =?utf-8?B?562U5aSNOiBbUEFUQ0ggdjIgMy81XSBtbWM6IG1lZGlhdGVrOiBBZGQgUE0g?=
 =?utf-8?Q?support_for_MMC_driver?=
In-Reply-To: <CAPDyKFqA=9mgzGkeBjkMxr3jhqxnEYov_4rf=OfdQ7_rAHicyw@mail.gmail.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-4-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFqA=9mgzGkeBjkMxr3jhqxnEYov_4rf=OfdQ7_rAHicyw@mail.gmail.com>
Message-ID: <B077351396223C4F8FE8C4C13672A9CA609796EC@mtkmbs33n1>

Dear Ulf,

Thanks for your review,
Please help to check my comments:

> -----????-----
> ???: Ulf Hansson [mailto:ulf.hansson at linaro.org]
> ????: 2015?3?31? 22:47
> ???: Chaotian Jing (???)
> ??: Rob Herring; Matthias Brugger; Chris Ball; Mark Rutland; JamesJJ Liao
> (???); srv_heupstream; Arnd Bergmann; devicetree at vger.kernel.org;
> HONGZHOU Yang; Catalin Marinas; linux-mmc; Will Deacon;
> linux-kernel at vger.kernel.org; linux-gpio at vger.kernel.org; Sascha Hauer;
> Yingjoe Chen (???); Eddie Huang (???); Bin Zhang (??);
> linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org
> ??: Re: [PATCH v2 3/5] mmc: mediatek: Add PM support for MMC driver
> 
> On 17 March 2015 at 04:13, Chaotian Jing <chaotian.jing at mediatek.com>
> wrote:
> > Add PM support for Mediatek MMC driver
> >
> > Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> > ---
> >  drivers/mmc/host/mtk-sd.c | 94
> > ++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 93 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > index 86c999b..e02f6a6 100644
> > --- a/drivers/mmc/host/mtk-sd.c
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -21,6 +21,7 @@
> >  #include <linux/of_irq.h>
> >  #include <linux/of_gpio.h>
> >  #include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> >  #include <linux/regulator/consumer.h>  #include <linux/spinlock.h>
> >
> > @@ -223,6 +224,7 @@
> >  #define MSDC_OCR_AVAIL      (MMC_VDD_28_29 | MMC_VDD_29_30
> \
> >                 | MMC_VDD_30_31 | MMC_VDD_31_32 |
> MMC_VDD_32_33)
> >
> > +#define MTK_MMC_AUTOSUSPEND_DELAY      500
> >  #define CMD_TIMEOUT         (HZ/10 * 5)        /* 100ms x5 */
> >  #define DAT_TIMEOUT         (HZ    * 5)        /* 1000ms x5 */
> >
> > @@ -535,6 +537,38 @@ static void msdc_set_mclk(struct msdc_host *host,
> int ddr, u32 hz)
> >         dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);  }
> >
> > +#ifdef CONFIG_PM
> 
> I suggest you move this complete code snippets within the ifdefs for where the
> runtime PM callbacks is implemented.
> 
I will remove the CONFIG_PM, because that if the kernel config do not enable CONFIG_PM, it still need do gate/ungate clock.
> > +static int msdc_gate_clock(struct msdc_host *host) {
> > +       int ret = 0;
> > +       unsigned long flags;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       /* disable SD/MMC/SDIO bus clock */
> > +       sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE,
> MSDC_MS);
> 
> This seems like it also belongs in the ->set_ios() function, when the rate
> requested by the core is zero!? Maybe that's already dealt with?
Yes, but it is not the same, the set_ios() set the bus clock to 0, only need set the MODE to MSDC_MS.
But the gate clock will gate the source clock of MSDC host, when the host is idle, runtime pm will gate it, but the ios->clock is not 0.
> 
> > +       /* turn off SDHC functional clock */
> > +       clk_disable(host->src_clk);
> 
> Change to clk_disable_unprepare() and move it outside the spin_lock.
> 
OK, will fix it at next revision.
> > +       spin_unlock_irqrestore(&host->lock, flags);
> > +       return ret;
> > +}
> > +
> > +static void msdc_ungate_clock(struct msdc_host *host) {
> > +       unsigned long flags;
> > +
> > +       spin_lock_irqsave(&host->lock, flags);
> > +       clk_enable(host->src_clk);
> 
> Change to clk_prepare_enable() and move it outside the spin_lock.
> 
OK, will fix it at next revision,
> > +       /* enable SD/MMC/SDIO bus clock:
> > +        * it will be automatically gated when the bus is idle
> > +        * (set MSDC_CFG_CKPDN bit to have it always on)
> > +        */
> > +       sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE,
> MSDC_SDMMC);
> > +       while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
> > +               cpu_relax();
> 
> I guess you already have this piece of code in ->set_ios() in some form!?
> 
> What's missing here is a kind of a save/restore mechanism of the clock. You
> need to save the value for the clock in msdc_ungate_clock() and restore the
> clock here. Else you might end up ungating the clock when it actually should
> remain gated.
> 
When we ungate the clock or change the frequency of the clock, both need wait the clock stable.

> > +       spin_unlock_irqrestore(&host->lock, flags); } #endif
> > +
> >  static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
> >                 struct mmc_request *mrq, struct mmc_command *cmd)
> {
> > @@ -702,6 +736,9 @@ static void msdc_request_done(struct msdc_host
> *host, struct mmc_request *mrq)
> >         if (mrq->data)
> >                 msdc_unprepare_data(host, mrq);
> >         mmc_request_done(host->mmc, mrq);
> > +
> > +       pm_runtime_mark_last_busy(host->dev);
> > +       pm_runtime_put_autosuspend(host->dev);
> >  }
> >
> >  /* returns true if command is fully handled; returns false otherwise
> > */ @@ -863,6 +900,8 @@ static void msdc_ops_request(struct mmc_host
> *mmc, struct mmc_request *mrq)
> >         }
> >         spin_unlock_irqrestore(&host->lock, flags);
> >
> > +       pm_runtime_get_sync(host->dev);
> > +
> >         if (mrq->data)
> >                 msdc_prepare_data(host, mrq);
> >
> > @@ -1003,6 +1042,8 @@ static int msdc_ops_switch_volt(struct mmc_host
> > *mmc, struct mmc_ios *ios)
> >
> >         if (!IS_ERR(mmc->supply.vqmmc)) {
> >
> > +               pm_runtime_get_sync(host->dev);
> > +
> >                 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
> >                         min_uv = 3300000;
> >                         max_uv = 3300000; @@ -1011,6 +1052,9 @@
> static
> > int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
> >                         max_uv = 1800000;
> >                 } else {
> >                         dev_err(host->dev, "Unsupported signal
> > voltage!\n");
> > +
> > +                       pm_runtime_mark_last_busy(host->dev);
> > +                       pm_runtime_put_autosuspend(host->dev);
> >                         return -EINVAL;
> 
> I suggest to assign a local "ret" variable which value you can return at the end
> of this function. Thus you won't need to duplicate the
> pm_runtime*() calls.
> 
OK, will fix at next revision.
> >                 }
> >
> > @@ -1022,6 +1066,8 @@ static int msdc_ops_switch_volt(struct mmc_host
> *mmc, struct mmc_ios *ios)
> >                 }
> >         }
> >
> > +       pm_runtime_mark_last_busy(host->dev);
> > +       pm_runtime_put_autosuspend(host->dev);
> >         return ret;
> >  }
> >
> > @@ -1186,6 +1232,8 @@ static void msdc_ops_set_ios(struct mmc_host
> *mmc, struct mmc_ios *ios)
> >         int ret;
> >         u32 ddr = 0;
> >
> > +       pm_runtime_get_sync(host->dev);
> > +
> >         if (ios->timing == MMC_TIMING_UHS_DDR50)
> >                 ddr = 1;
> >
> > @@ -1230,6 +1278,9 @@ static void msdc_ops_set_ios(struct mmc_host
> > *mmc, struct mmc_ios *ios)
> >
> >         if (host->mclk != ios->clock || host->ddr != ddr)
> >                 msdc_set_mclk(host, ddr, ios->clock);
> > +
> > +       pm_runtime_mark_last_busy(host->dev);
> > +       pm_runtime_put_autosuspend(host->dev);
> >  }
> >
> >  static struct mmc_host_ops mt_msdc_ops = { @@ -1341,6 +1392,11 @@
> > static int msdc_drv_probe(struct platform_device *pdev)
> >         platform_set_drvdata(pdev, mmc);
> >         clk_prepare(host->src_clk);
> >
> > +       pm_runtime_enable(host->dev);
> > +       pm_runtime_get_sync(host->dev);
> > +       pm_runtime_set_autosuspend_delay(host->dev,
> MTK_MMC_AUTOSUSPEND_DELAY);
> > +       pm_runtime_use_autosuspend(host->dev);
> 
> This shall be changed to the following:
> 
Ok, will fix it.
> pm_runtime_set_active();
> pm_runtime_set_autosuspend_delay(host->dev,
> MTK_MMC_AUTOSUSPEND_DELAY);
> pm_runtime_use_autosuspend(host->dev);
> pm_runtime_enable(host->dev);
> 
> ... and to simplify error handling, move it just prior mmc_add_host().
> 	
Will fix it at next revision.
> > +
> >         ret = devm_request_irq(&pdev->dev, (unsigned int) host->irq,
> msdc_irq,
> >                 IRQF_TRIGGER_LOW | IRQF_ONESHOT, pdev->name,
> host);
> >         if (ret)
> > @@ -1348,10 +1404,15 @@ static int msdc_drv_probe(struct
> > platform_device *pdev)
> >
> >         ret = mmc_add_host(mmc);
> >         if (ret)
> > -               goto release;
> > +               goto end;
> >
> > +       pm_runtime_mark_last_busy(host->dev);
> > +       pm_runtime_put_autosuspend(host->dev);
> 
> According to above, remove these pm_runtime_*() calls.
> 
Okay.
> >         return 0;
> >
> > +end:
> > +       pm_runtime_put_sync(host->dev);
> 
> According to above, remove the pm_runtime_put_sync().
> Will remove it at next revision,
> > +       pm_runtime_disable(host->dev);
> >  release:
> >         platform_set_drvdata(pdev, NULL);
> >         msdc_deinit_hw(host);
> > @@ -1364,6 +1425,7 @@ release_mem:
> >                 dma_free_coherent(&pdev->dev,
> >                         MAX_BD_NUM * sizeof(struct
> mt_bdma_desc),
> >                         host->dma.bd, host->dma.bd_addr);
> > +
> >  host_free:
> >         mmc_free_host(mmc);
> >
> > @@ -1378,10 +1440,14 @@ static int msdc_drv_remove(struct
> platform_device *pdev)
> >         mmc = platform_get_drvdata(pdev);
> >         host = mmc_priv(mmc);
> >
> > +       pm_runtime_get_sync(host->dev);
> > +
> >         platform_set_drvdata(pdev, NULL);
> >         mmc_remove_host(host->mmc);
> >         msdc_deinit_hw(host);
> >
> > +       pm_runtime_put_sync(host->dev);
> 
> Change to pm_runtime_put_noidle() and reverse the order of the call to
> pm_runtime_disable().
> 
Ok. Will fix it at next revision,
> > +       pm_runtime_disable(host->dev);
> >         dma_free_coherent(&pdev->dev,
> >                         MAX_GPD_NUM * sizeof(struct
> mt_gpdma_desc),
> >                         host->dma.gpd, host->dma.gpd_addr); @@
> -1393,6
> > +1459,31 @@ static int msdc_drv_remove(struct platform_device *pdev)
> >         return 0;
> >  }
> >
> > +#ifdef CONFIG_PM
> > +static int msdc_runtime_suspend(struct device *dev) {
> > +       int ret = 0;
> > +       struct mmc_host *mmc = dev_get_drvdata(dev);
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +
> > +       ret = msdc_gate_clock(host);
> > +       return ret;
> > +}
> > +
> > +static int msdc_runtime_resume(struct device *dev) {
> > +       struct mmc_host *mmc = dev_get_drvdata(dev);
> > +       struct msdc_host *host = mmc_priv(mmc);
> > +
> > +       msdc_ungate_clock(host);
> > +       return 0;
> > +}
> > +#endif
> > +
> > +static const struct dev_pm_ops msdc_dev_pm_ops = {
> > +       SET_RUNTIME_PM_OPS(msdc_runtime_suspend,
> msdc_runtime_resume,
> > +NULL) };
> > +
> >  static const struct of_device_id msdc_of_ids[] = {
> >         {   .compatible = "mediatek,mt8135-mmc", },
> >         {}
> > @@ -1404,6 +1495,7 @@ static struct platform_driver mt_msdc_driver = {
> >         .driver = {
> >                 .name = "mtk-msdc",
> >                 .of_match_table = msdc_of_ids,
> > +               .pm = &msdc_dev_pm_ops,
> >         },
> >  };
> >
> > --
> > 1.8.1.1.dirty
> >
> 
> Kind regards
> Uffe

************* Email Confidentiality Notice ********************
The information contained in this e-mail message (including any 
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be 
conveyed only to the designated recipient(s). Any use, dissemination, 
distribution, printing, retaining or copying of this e-mail (including its 
attachments) by unintended recipient(s) is strictly prohibited and may 
be unlawful. If you are not an intended recipient of this e-mail, or believe 
that you have received this e-mail in error, please notify the sender 
immediately (by replying to this e-mail), delete any and all copies of 
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!

From edubezval at gmail.com  Mon Apr  6 18:45:48 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 18:45:48 -0700
Subject: [PATCH 01/13] thermal: Make temperatures consistently unsigned
 long
In-Reply-To: <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407014546.GA4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:48PM +0100, Sascha Hauer wrote:
> The thermal framework uses int, long and unsigned long for temperatures
> in millicelsius. The majority of functions uses unsigned long, so change
> the remaining functions to use this type aswell.

I believe it make sense to change all to be int. int covers for the
required temperature range. 

Rui is just introducing the concept of invalid temp, which is below 0 K.

> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/thermal_core.c | 10 +++++-----
>  include/linux/thermal.h        |  6 +++---

This change is not that straight forward as it looks like. 

In order to standardize this, apart from the thermal core
we will need to make drivers aware of the change too.
That will require changing the thermal zone device ops and all its
users, for the trip temperature, temperature, and hysteresis cases.

>  2 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index 174d3bc..0e4ad7c 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -378,7 +378,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
>  
>  	if (trip_type == THERMAL_TRIP_CRITICAL) {
>  		dev_emerg(&tz->device,
> -			  "critical temperature reached(%d C),shutting down\n",
> +			  "critical temperature reached(%lu C),shutting down\n",
>  			  tz->temperature / 1000);
>  		orderly_poweroff(true);
>  	}
> @@ -453,7 +453,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
>  
>  static void update_temperature(struct thermal_zone_device *tz)
>  {
> -	long temp;
> +	unsigned long temp;
>  	int ret;
>  
>  	ret = thermal_zone_get_temp(tz, &temp);
> @@ -469,7 +469,7 @@ static void update_temperature(struct thermal_zone_device *tz)
>  	mutex_unlock(&tz->lock);
>  
>  	trace_thermal_temperature(tz);
> -	dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
> +	dev_dbg(&tz->device, "last_temperature=%lu, current_temperature=%lu\n",
>  				tz->last_temperature, tz->temperature);
>  }
>  
> @@ -512,7 +512,7 @@ static ssize_t
>  temp_show(struct device *dev, struct device_attribute *attr, char *buf)
>  {
>  	struct thermal_zone_device *tz = to_thermal_zone(dev);
> -	long temperature;
> +	unsigned long temperature;
>  	int ret;
>  
>  	ret = thermal_zone_get_temp(tz, &temperature);
> @@ -520,7 +520,7 @@ temp_show(struct device *dev, struct device_attribute *attr, char *buf)
>  	if (ret)
>  		return ret;
>  
> -	return sprintf(buf, "%ld\n", temperature);
> +	return sprintf(buf, "%lu\n", temperature);
>  }
>  
>  static ssize_t
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 5eac316..db6c12b 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -180,9 +180,9 @@ struct thermal_zone_device {
>  	int trips;
>  	int passive_delay;
>  	int polling_delay;
> -	int temperature;
> -	int last_temperature;
> -	int emul_temperature;
> +	unsigned long temperature;
> +	unsigned long last_temperature;
> +	unsigned long emul_temperature;
>  	int passive;
>  	unsigned int forced_passive;
>  	struct thermal_zone_device_ops *ops;

Something like the following would be required to do a standardization.
Of course, the code below requires changing drivers too:

diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 6bbe11c..84c9777 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -92,7 +92,7 @@ struct thermal_zone_device_ops {
 		     struct thermal_cooling_device *);
 	int (*unbind) (struct thermal_zone_device *,
 		       struct thermal_cooling_device *);
-	int (*get_temp) (struct thermal_zone_device *, unsigned long *);
+	int (*get_temp) (struct thermal_zone_device *, int *);
 	int (*get_mode) (struct thermal_zone_device *,
 			 enum thermal_device_mode *);
 	int (*set_mode) (struct thermal_zone_device *,
@@ -100,15 +100,15 @@ struct thermal_zone_device_ops {
 	int (*get_trip_type) (struct thermal_zone_device *, int,
 		enum thermal_trip_type *);
 	int (*get_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long *);
+			      int *);
 	int (*set_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long);
+			      int);
 	int (*get_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long *);
+			      int *);
 	int (*set_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long);
-	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
-	int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
+			      int);
+	int (*get_crit_temp) (struct thermal_zone_device *, int *);
+	int (*set_emul_temp) (struct thermal_zone_device *, int);
 	int (*get_trend) (struct thermal_zone_device *, int,
 			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
@@ -321,9 +321,9 @@ struct thermal_genl_event {
  *		   temperature.
  */
 struct thermal_zone_of_device_ops {
-	int (*get_temp)(void *, long *);
-	int (*get_trend)(void *, long *);
-	int (*set_emul_temp)(void *, unsigned long);
+	int (*get_temp)(void *, int *);
+	int (*get_trend)(void *, int *);
+	int (*set_emul_temp)(void *, int);
 };
 
 /**
@@ -336,8 +336,8 @@ struct thermal_zone_of_device_ops {
 
 struct thermal_trip {
 	struct device_node *np;
-	unsigned long int temperature;
-	unsigned long int hysteresis;
+	int temperature;
+	int hysteresis;
 	enum thermal_trip_type type;
 };
 
@@ -395,7 +395,7 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
 				   const struct thermal_cooling_device_ops *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
+int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
 
 int get_tz_trend(struct thermal_zone_device *, int);
 struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -446,7 +446,7 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
 		const char *name)
 { return ERR_PTR(-ENODEV); }
 static inline int thermal_zone_get_temp(
-		struct thermal_zone_device *tz, unsigned long *temp)
+		struct thermal_zone_device *tz, int *temp)
 { return -ENODEV; }
 static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
 { return -ENODEV; }


> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/f80c7d4d/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 18:47:08 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 18:47:08 -0700
Subject: [PATCH 01/13] thermal: Make temperatures consistently unsigned
 long
In-Reply-To: <20150327190750.GZ9742@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
 <9hhzj6y217d.fsf@e105922-lin.cambridge.arm.com>
 <20150327190750.GZ9742@pengutronix.de>
Message-ID: <20150407014707.GB4648@localhost.localdomain>

On Fri, Mar 27, 2015 at 08:07:50PM +0100, Sascha Hauer wrote:
> On Fri, Mar 27, 2015 at 10:18:14AM +0000, Punit Agrawal wrote:
> > Hi Sascha,
> > 
> > Sascha Hauer <s.hauer at pengutronix.de> writes:
> > 
> > > The thermal framework uses int, long and unsigned long for temperatures
> > > in millicelsius. The majority of functions uses unsigned long, so change
> > > the remaining functions to use this type aswell.
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > 
> > I'd suggest changing to long instead. It would allow the use of the
> > thermal framework in environments where temperatures are below 0C -
> > quite easily reached in many parts of the world.
> 
> I agree to use a signed type. I also found it not so nice that the thermal
> core does not support negative temperatures. I only chose unsigned long
> because the patch got smallest that way, but I already expected this
> answer ;)
> We could also use int instead of long. INT_MAX ?mC is still enough for using
> a computer on the surface of the sun (Not for the center though)

Agreed, int is the preferred type.


> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/5037ca27/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 18:49:00 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 18:49:00 -0700
Subject: [PATCH 02/13] thermal: trivial: fix typo in comment
In-Reply-To: <1427385240-6086-3-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-3-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407014859.GC4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:49PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Acked-by: Eduardo Valentin <edubezval at gmail.com>

> ---
>  drivers/thermal/thermal_core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index 0e4ad7c..c735ac4c 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -402,7 +402,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
>  }
>  
>  /**
> - * thermal_zone_get_temp() - returns its the temperature of thermal zone
> + * thermal_zone_get_temp() - returns the temperature of a thermal zone
>   * @tz: a valid pointer to a struct thermal_zone_device
>   * @temp: a valid pointer to where to store the resulting temperature.
>   *
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/c7d23f2a/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 19:08:30 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:08:30 -0700
Subject: [PATCH 04/13] thermal: Fix not emulating critical temperatures
In-Reply-To: <20150327052318.GO9742@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-5-git-send-email-s.hauer@pengutronix.de>
 <CADGdYn5vaPu4+yhjs5c3QuCnz-LtL2Z2qRENjsizpO6D1gVOSg@mail.gmail.com>
 <20150327052318.GO9742@pengutronix.de>
Message-ID: <20150407020829.GD4648@localhost.localdomain>

On Fri, Mar 27, 2015 at 06:23:18AM +0100, Sascha Hauer wrote:
> Hi Amit,
> 
> On Fri, Mar 27, 2015 at 08:35:50AM +0530, amit daniel kachhap wrote:
> > Hi Sascha,
> > 
> > > -#ifdef CONFIG_THERMAL_EMULATION
> > > -       if (!tz->emul_temperature)
> > > -               goto skip_emul;
> > > -
> > > -       for (count = 0; count < tz->trips; count++) {
> > > -               ret = tz->ops->get_trip_type(tz, count, &type);
> > > -               if (!ret && type == THERMAL_TRIP_CRITICAL) {
> > > -                       ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
> > > -                       break;
> > > -               }
> > > -       }
> > > -
> > > -       if (ret)
> > > -               goto skip_emul;
> > >
> > > -       if (*temp < crit_temp)
> > I guess this check is confusing. Actually instead of returning
> > emulating temperature it is returning actual temperature. But the
> > important thing to look here is that actual temperature is higher than
> > critical temperature. So this check prevents the user from suppressing
> > the critical temperature and hence prevents from burning up the chip.
> 
> Indeed the check is confusing, but now it makes perfectly sense. I'll
> look at the patch again and maybe turn into a patch just adding a
> comment to clarify this.

That will be great. Thanks Sascha.

> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/2f5c1bfe/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 19:23:08 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:23:08 -0700
Subject: [PATCH 05/13] thermal: inline only once used function
In-Reply-To: <1427385240-6086-6-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-6-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407022307.GE4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:52PM +0100, Sascha Hauer wrote:
> Inline update_temperature into its only caller to make the code
> more readable.

I am not sure I understand how this is improving readability, can you
please elaborate?

The way it is now it is more modular at least.

> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/thermal_core.c | 16 +++++-----------
>  1 file changed, 5 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index ebca854..6d0fdad 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -431,11 +431,15 @@ exit:
>  }
>  EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
>  
> -static void update_temperature(struct thermal_zone_device *tz)
> +void thermal_zone_device_update(struct thermal_zone_device *tz)
>  {
> +	int count;
>  	unsigned long temp;
>  	int ret;
>  
> +	if (!tz->ops->get_temp)
> +		return;
> +
>  	ret = thermal_zone_get_temp(tz, &temp);
>  	if (ret) {
>  		dev_warn(&tz->device, "failed to read out thermal zone %d\n",
> @@ -451,16 +455,6 @@ static void update_temperature(struct thermal_zone_device *tz)
>  	trace_thermal_temperature(tz);
>  	dev_dbg(&tz->device, "last_temperature=%lu, current_temperature=%lu\n",
>  				tz->last_temperature, tz->temperature);
> -}
> -
> -void thermal_zone_device_update(struct thermal_zone_device *tz)
> -{
> -	int count;
> -
> -	if (!tz->ops->get_temp)
> -		return;
> -
> -	update_temperature(tz);
>  
>  	for (count = 0; count < tz->trips; count++)
>  		handle_thermal_trip(tz, count);
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/9e258001/attachment-0001.sig>

From edubezval at gmail.com  Mon Apr  6 19:27:52 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:27:52 -0700
Subject: [PATCH 07/13] thermal: of: streamline .get_temp callbacks
In-Reply-To: <1427385240-6086-8-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-8-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407022750.GF4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:54PM +0100, Sascha Hauer wrote:
> In the thermal framework it was decided that temperatures can't
> be negative, so let the .get_temp callback in struct
> thermal_zone_of_device_ops take an unsigned long pointer for
> the temperature like the .get_temp callback in
> struct thermal_zone_device_ops does.

This change is required. However, better we move to the direction of
using signed type for temperature. However, we want to have int instead
of long though.

> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/hwmon/lm75.c                               | 2 +-
>  drivers/hwmon/ntc_thermistor.c                     | 2 +-
>  drivers/hwmon/tmp102.c                             | 2 +-
>  drivers/input/touchscreen/sun4i-ts.c               | 2 +-
>  drivers/thermal/rockchip_thermal.c                 | 2 +-
>  drivers/thermal/samsung/exynos_tmu.c               | 2 +-
>  drivers/thermal/tegra_soctherm.c                   | 2 +-
>  drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +-
>  include/linux/thermal.h                            | 2 +-
>  9 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index fe41d5a..9df3ca3 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -104,7 +104,7 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
>  
>  /* sysfs attributes for hwmon */
>  
> -static int lm75_read_temp(void *dev, long *temp)
> +static int lm75_read_temp(void *dev, unsigned long *temp)
>  {
>  	struct lm75_data *data = lm75_update_device(dev);
>  
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index 112e4d4..12cb333 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -430,7 +430,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
>  	return -EINVAL;
>  }
>  
> -static int ntc_read_temp(void *dev, long *temp)
> +static int ntc_read_temp(void *dev, unsigned long *temp)
>  {
>  	struct ntc_data *data = dev_get_drvdata(dev);
>  	int ohm;
> diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
> index 9da2735..25bd72b 100644
> --- a/drivers/hwmon/tmp102.c
> +++ b/drivers/hwmon/tmp102.c
> @@ -98,7 +98,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
>  	return tmp102;
>  }
>  
> -static int tmp102_read_temp(void *dev, long *temp)
> +static int tmp102_read_temp(void *dev, unsigned long *temp)
>  {
>  	struct tmp102 *tmp102 = tmp102_update_device(dev);
>  
> diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
> index b93a28b..26a7cf5 100644
> --- a/drivers/input/touchscreen/sun4i-ts.c
> +++ b/drivers/input/touchscreen/sun4i-ts.c
> @@ -198,7 +198,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
>  	return 0;
>  }
>  
> -static int sun4i_get_tz_temp(void *data, long *temp)
> +static int sun4i_get_tz_temp(void *data, unsigned long *temp)
>  {
>  	return sun4i_get_temp(data, temp);
>  }
> diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
> index 3aa46ac..67dfc67 100644
> --- a/drivers/thermal/rockchip_thermal.c
> +++ b/drivers/thermal/rockchip_thermal.c
> @@ -366,7 +366,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
>  	return IRQ_HANDLED;
>  }
>  
> -static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
> +static int rockchip_thermal_get_temp(void *_sensor, unsigned long *out_temp)
>  {
>  	struct rockchip_thermal_sensor *sensor = _sensor;
>  	struct rockchip_thermal_data *thermal = sensor->thermal;
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 1d30b09..5f721f2 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -713,7 +713,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
>  	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>  }
>  
> -static int exynos_get_temp(void *p, long *temp)
> +static int exynos_get_temp(void *p, unsigned long *temp)
>  {
>  	struct exynos_tmu_data *data = p;
>  
> diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c
> index 9197fc0..1c4e455 100644
> --- a/drivers/thermal/tegra_soctherm.c
> +++ b/drivers/thermal/tegra_soctherm.c
> @@ -306,7 +306,7 @@ static long translate_temp(u16 val)
>  	return t;
>  }
>  
> -static int tegra_thermctl_get_temp(void *data, long *out_temp)
> +static int tegra_thermctl_get_temp(void *data, unsigned long *out_temp)
>  {
>  	struct tegra_thermctl_zone *zone = data;
>  	u32 val;
> diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> index 7f8e5f3..f480a01 100644
> --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> @@ -76,7 +76,7 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
>  
>  /* thermal zone ops */
>  /* Get temperature callback function for thermal zone*/
> -static inline int __ti_thermal_get_temp(void *devdata, long *temp)
> +static inline int __ti_thermal_get_temp(void *devdata, unsigned long *temp)
>  {
>  	struct thermal_zone_device *pcb_tz = NULL;
>  	struct ti_thermal_data *data = devdata;
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index ba2e29a..2f77091 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -272,7 +272,7 @@ struct thermal_genl_event {
>   *		   temperature.
>   */
>  struct thermal_zone_of_device_ops {
> -	int (*get_temp)(void *, long *);
> +	int (*get_temp)(void *, unsigned long *);
>  	int (*get_trend)(void *, int trend, enum thermal_trend *);
>  	int (*set_emul_temp)(void *, unsigned long);
>  };
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/fac001a2/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 19:40:28 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:40:28 -0700
Subject: [PATCH 12/13] thermal: Add support for hardware-tracked trip
 points
In-Reply-To: <1427385240-6086-13-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-13-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407024027.GG4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:59PM +0100, Sascha Hauer wrote:
> This adds support for hardware-tracked trip points to the device tree
> thermal sensor framework.
> 
> The framework supports an arbitrary number of trip points. Whenever
> the current temperature is updated, the trip points immediately
> below and above the current temperature are found. A .set_trips
> callback is then called with the temperatures. If there is no trip
> point above or below the current temperature, the passed trip
> temperature will be ULONG_MAX or 0 respectively. In this callback,
> the driver should program the hardware such that it is notified
> when either of these trip points are triggered. When a trip point
> is triggered, the driver should call `thermal_zone_device_update'
> for the respective thermal zone. This will cause the trip points
> to be updated again.
> 
> If .set_trips is not implemented, the framework behaves as before.
> 
> This patch is based on an earlier version from Mikko Perttunen
> <mikko.perttunen at kapsi.fi>
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/thermal_core.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/thermal.h        |  3 +++
>  2 files changed, 44 insertions(+)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index dcdf45e..7138f8f 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -434,6 +434,45 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
>  }
>  EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
>  
> +static void thermal_zone_set_trips(struct thermal_zone_device *tz)
> +{
> +	unsigned long low = 0;
> +	unsigned long high = ULONG_MAX;
> +	unsigned long trip_temp, hysteresis;
> +	unsigned long temp = tz->temperature;
> +	int i;
> +
> +	if (!tz->ops->set_trips)
> +		return;
> +
> +	/* No need to change trip points */
> +	if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
> +		return;
> +
> +	for (i = 0; i < tz->trips; i++) {
> +		unsigned long trip_low;
> +
> +		tz->ops->get_trip_temp(tz, i, &trip_temp);
> +		tz->ops->get_trip_hyst(tz, i, &hysteresis);
> +
> +		trip_low = trip_temp - hysteresis;
> +
> +		if (trip_low < temp && trip_low > low)
> +			low = trip_low;
> +
> +		if (trip_temp > temp && trip_temp < high)
> +			high = trip_temp;
> +	}
> +
> +	tz->prev_low_trip = low;
> +	tz->prev_high_trip = high;
> +
> +	dev_dbg(&tz->device, "new temperature boundaries: %lu < x < %lu\n",
> +			low, high);
> +
> +	tz->ops->set_trips(tz, low, high);
> +}
> +
>  void thermal_zone_device_update(struct thermal_zone_device *tz)
>  {
>  	int count;
> @@ -460,6 +499,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  	dev_dbg(&tz->device, "last_temperature=%lu, current_temperature=%lu\n",
>  				tz->last_temperature, tz->temperature);
>  
> +	thermal_zone_set_trips(tz);

Do we need to lock the tz->lock to perform this operation of setting the
hardware trip points?

> +
>  	for (count = 0; count < tz->trips; count++)
>  		handle_thermal_trip(tz, count);
>  }
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index ac2897c..b870702 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
>  	int (*unbind) (struct thermal_zone_device *,
>  		       struct thermal_cooling_device *);
>  	int (*get_temp) (struct thermal_zone_device *, unsigned long *);
> +	int (*set_trips) (struct thermal_zone_device *, unsigned long, unsigned long);
>  	int (*get_mode) (struct thermal_zone_device *,
>  			 enum thermal_device_mode *);
>  	int (*set_mode) (struct thermal_zone_device *,
> @@ -183,6 +184,8 @@ struct thermal_zone_device {
>  	unsigned long temperature;
>  	unsigned long last_temperature;
>  	unsigned long emul_temperature;
> +	unsigned long prev_low_trip;
> +	unsigned long prev_high_trip;
>  	int passive;
>  	unsigned int forced_passive;
>  	const struct thermal_zone_device_ops *ops;
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/d4723b2a/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 19:43:08 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:43:08 -0700
Subject: [PATCH 13/13] thermal: of: implement .set_trips for device tree
 thermal zones
In-Reply-To: <1427385240-6086-14-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-14-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407024307.GH4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:54:00PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/of-thermal.c | 12 ++++++++++++
>  include/linux/thermal.h      |  1 +
>  2 files changed, 13 insertions(+)

Can you please include at least one user of this call back in your patch
series?

> 
> diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> index 9b63193..a3de5de 100644
> --- a/drivers/thermal/of-thermal.c
> +++ b/drivers/thermal/of-thermal.c
> @@ -97,6 +97,17 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
>  	return data->ops->get_temp(data->sensor_data, temp);
>  }
>  
> +static int of_thermal_set_trips(struct thermal_zone_device *tz,
> +			       unsigned long low, unsigned long high)
> +{
> +	struct __thermal_zone *data = tz->devdata;
> +
> +	if (!data->ops || !data->ops->set_trips)
> +		return -ENOSYS;
> +
> +	return data->ops->set_trips(data->sensor_data, low, high);
> +}
> +
>  /**
>   * of_thermal_get_ntrips - function to export number of available trip
>   *			   points.
> @@ -367,6 +378,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
>  
>  static const struct thermal_zone_device_ops of_thermal_ops = {
>  	.get_temp = of_thermal_get_temp,
> +	.set_trips = of_thermal_set_trips,
>  	.get_trend = of_thermal_get_trend,
>  	.set_emul_temp = of_thermal_set_emul_temp,
>  
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index b870702..84a5b5d 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -276,6 +276,7 @@ struct thermal_genl_event {
>   */
>  struct thermal_zone_of_device_ops {
>  	int (*get_temp)(void *, unsigned long *);
> +	int (*set_trips)(void *, unsigned long, unsigned long);

Could you please keep the kernel doc entry up to date? I know we donot
have entries for all structs, but I am working in improving this.

>  	int (*get_trend)(void *, int trend, enum thermal_trend *);
>  	int (*set_emul_temp)(void *, unsigned long);
>  };
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/26e049b6/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 19:56:32 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 19:56:32 -0700
Subject: [PATCH 03/13] thermal: remove useless call to
 thermal_zone_device_set_polling
In-Reply-To: <1427385240-6086-4-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-4-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407025630.GJ4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:50PM +0100, Sascha Hauer wrote:
> When the thermal zone has no get_temp callback then thermal_zone_device_register()
> calls thermal_zone_device_set_polling() with a polling delay of 0. This
> only cancels the poll_queue. Since the poll_queue hasn't been scheduled this
> is a no-op. Remove it.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

This seams reasonable to me:

Acked-by: Eduardo Valentin <edubezval at gmail.com>

> ---
>  drivers/thermal/thermal_core.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index c735ac4c..dcea909 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -1571,9 +1571,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
>  
>  	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
>  
> -	if (!tz->ops->get_temp)
> -		thermal_zone_device_set_polling(tz, 0);
> -
>  	thermal_zone_device_update(tz);
>  
>  	return tz;
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/6f8bf09a/attachment-0001.sig>

From edubezval at gmail.com  Mon Apr  6 20:19:52 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 20:19:52 -0700
Subject: [PATCH 06/13] thermal: streamline get_trend callbacks
In-Reply-To: <1427385240-6086-7-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-7-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407031950.GK4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:53PM +0100, Sascha Hauer wrote:
> The .get_trend callback in struct thermal_zone_device_ops has the prototype:
> 
> 	int (*get_trend) (struct thermal_zone_device *, int,
> 			  enum thermal_trend *);
> 
> whereas the .get_trend callback in struct thermal_zone_of_device_ops has:
> 
> 	int (*get_trend)(void *, long *);
> 
> Streamline both prototypes and add the trip argument to the OF callback
> aswell and use enum thermal_trend * instead of an integer pointer.
> 
> While the OF prototype may be the better one, this should be decided at
> framework level and not on OF level.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/of-thermal.c                       | 11 +---------
>  drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++++---------------
>  include/linux/thermal.h                            |  2 +-
>  3 files changed, 10 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> index 668fb1b..b39e22f 100644
> --- a/drivers/thermal/of-thermal.c
> +++ b/drivers/thermal/of-thermal.c
> @@ -187,24 +187,15 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
>  				enum thermal_trend *trend)
>  {
>  	struct __thermal_zone *data = tz->devdata;
> -	long dev_trend;
>  	int r;
>  
>  	if (!data->ops->get_trend)
>  		return -EINVAL;
>  
> -	r = data->ops->get_trend(data->sensor_data, &dev_trend);
> +	r = data->ops->get_trend(data->sensor_data, trip, trend);
>  	if (r)
>  		return r;
>  
> -	/* TODO: These intervals might have some thresholds, but in core code */
> -	if (dev_trend > 0)
> -		*trend = THERMAL_TREND_RAISING;
> -	else if (dev_trend < 0)
> -		*trend = THERMAL_TREND_DROPPING;
> -	else
> -		*trend = THERMAL_TREND_STABLE;
> -
>  	return 0;
>  }
>  
> diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> index a38c175..7f8e5f3 100644
> --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> @@ -238,7 +238,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
>  	return 0;
>  }
>  
> -static int __ti_thermal_get_trend(void *p, long *trend)
> +static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
>  {
>  	struct ti_thermal_data *data = p;
>  	struct ti_bandgap *bgp;
> @@ -251,22 +251,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
>  	if (ret)
>  		return ret;
>  
> -	*trend = tr;
> -
> -	return 0;
> -}
> -
> -/* Get the temperature trend callback functions for thermal zone */
> -static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
> -				int trip, enum thermal_trend *trend)
> -{
> -	int ret;
> -	long tr;
> -
> -	ret = __ti_thermal_get_trend(thermal->devdata, &tr);
> -	if (ret)
> -		return ret;
> -
>  	if (tr > 0)
>  		*trend = THERMAL_TREND_RAISING;
>  	else if (tr < 0)
> @@ -277,6 +261,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
>  	return 0;
>  }
>  
> +/* Get the temperature trend callback functions for thermal zone */
> +static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
> +				int trip, enum thermal_trend *trend)
> +{
> +	return __ti_thermal_get_trend(thermal->devdata, trip, trend);
> +}
> +
>  /* Get critical temperature callback functions for thermal zone */
>  static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
>  				    unsigned long *temp)
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index db6c12b..ba2e29a 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -273,7 +273,7 @@ struct thermal_genl_event {
>   */
>  struct thermal_zone_of_device_ops {
>  	int (*get_temp)(void *, long *);
> -	int (*get_trend)(void *, long *);
> +	int (*get_trend)(void *, int trend, enum thermal_trend *);

Could you please keep the kernel doc entry up to date?


Apart from that, looks good to me.

>  	int (*set_emul_temp)(void *, unsigned long);
>  };
>  
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/71e18521/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 20:25:23 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 20:25:23 -0700
Subject: [PATCH 09/13] thermal: of: always set sensor related callbacks
In-Reply-To: <1427385240-6086-10-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-10-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407032522.GL4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:56PM +0100, Sascha Hauer wrote:
> Now that the thermal core treats -ENOSYS like the callbacks were
> not present at all we no longer have to overwrite the ops during
> runtime but instead can always set them and return -ENOSYS if no
> sensor is registered.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/of-thermal.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> index b39e22f..df14fdd 100644
> --- a/drivers/thermal/of-thermal.c
> +++ b/drivers/thermal/of-thermal.c
> @@ -91,7 +91,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
>  {
>  	struct __thermal_zone *data = tz->devdata;
>  
> -	if (!data->ops->get_temp)
> +	if (!data->ops)
>  		return -EINVAL;
>  
>  	return data->ops->get_temp(data->sensor_data, temp);
> @@ -178,7 +178,7 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
>  	struct __thermal_zone *data = tz->devdata;
>  
>  	if (!data->ops || !data->ops->set_emul_temp)
> -		return -EINVAL;
> +		return -ENOSYS;
>  
>  	return data->ops->set_emul_temp(data->sensor_data, temp);
>  }
> @@ -189,8 +189,8 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
>  	struct __thermal_zone *data = tz->devdata;
>  	int r;
>  
> -	if (!data->ops->get_trend)
> -		return -EINVAL;
> +	if (!data->ops || !data->ops->get_trend)
> +		return -ENOSYS;
>  
>  	r = data->ops->get_trend(data->sensor_data, trip, trend);
>  	if (r)
> @@ -366,6 +366,10 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
>  }
>  
>  static struct thermal_zone_device_ops of_thermal_ops = {
> +	.get_temp = of_thermal_get_temp,
> +	.get_trend = of_thermal_get_trend,
> +	.set_emul_temp = of_thermal_set_emul_temp,
> +
>  	.get_mode = of_thermal_get_mode,
>  	.set_mode = of_thermal_set_mode,
>  
> @@ -399,13 +403,13 @@ thermal_zone_of_add_sensor(struct device_node *zone,
>  	if (!ops)
>  		return ERR_PTR(-EINVAL);
>  
> +	if (!ops->get_temp)
> +		return ERR_PTR(-EINVAL);
> +
>  	mutex_lock(&tzd->lock);
>  	tz->ops = ops;
>  	tz->sensor_data = data;
>  
> -	tzd->ops->get_temp = of_thermal_get_temp;
> -	tzd->ops->get_trend = of_thermal_get_trend;
> -	tzd->ops->set_emul_temp = of_thermal_set_emul_temp;

You may want to update the thermal_zone_of_sensor_unregister too.

>  	mutex_unlock(&tzd->lock);
>  
>  	return tzd;
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/06051543/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 20:27:40 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 20:27:40 -0700
Subject: [PATCH 11/13] thermal: of: make of_thermal_ops const
In-Reply-To: <1427385240-6086-12-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-12-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407032739.GM4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:58PM +0100, Sascha Hauer wrote:
> Now that we no longer modify the ops they can be const again. Also
> we no longer have to duplicate them.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Should this one be merged to patch 09/13?

> ---
>  drivers/thermal/of-thermal.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> index df14fdd..9b63193 100644
> --- a/drivers/thermal/of-thermal.c
> +++ b/drivers/thermal/of-thermal.c
> @@ -365,7 +365,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
>  	return -EINVAL;
>  }
>  
> -static struct thermal_zone_device_ops of_thermal_ops = {
> +static const struct thermal_zone_device_ops of_thermal_ops = {
>  	.get_temp = of_thermal_get_temp,
>  	.get_trend = of_thermal_get_trend,
>  	.set_emul_temp = of_thermal_set_emul_temp,
> @@ -539,10 +539,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
>  		return;
>  
>  	mutex_lock(&tzd->lock);
> -	tzd->ops->get_temp = NULL;
> -	tzd->ops->get_trend = NULL;
> -	tzd->ops->set_emul_temp = NULL;
> -
>  	tz->ops = NULL;
>  	tz->sensor_data = NULL;
>  	mutex_unlock(&tzd->lock);
> @@ -849,7 +845,6 @@ int __init of_parse_thermal_zones(void)
>  {
>  	struct device_node *np, *child;
>  	struct __thermal_zone *tz;
> -	struct thermal_zone_device_ops *ops;
>  
>  	np = of_find_node_by_name(NULL, "thermal-zones");
>  	if (!np) {
> @@ -873,29 +868,22 @@ int __init of_parse_thermal_zones(void)
>  			continue;
>  		}
>  
> -		ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
> -		if (!ops)
> -			goto exit_free;
> -
>  		tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
> -		if (!tzp) {
> -			kfree(ops);
> +		if (!tzp)
>  			goto exit_free;
> -		}
>  
>  		/* No hwmon because there might be hwmon drivers registering */
>  		tzp->no_hwmon = true;
>  
>  		zone = thermal_zone_device_register(child->name, tz->ntrips,
>  						    0, tz,
> -						    ops, tzp,
> +						    &of_thermal_ops, tzp,
>  						    tz->passive_delay,
>  						    tz->polling_delay);
>  		if (IS_ERR(zone)) {
>  			pr_err("Failed to build %s zone %ld\n", child->name,
>  			       PTR_ERR(zone));
>  			kfree(tzp);
> -			kfree(ops);
>  			of_thermal_free_zone(tz);
>  			/* attempting to build remaining zones still */
>  		}
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/46ab7b3a/attachment.sig>

From edubezval at gmail.com  Mon Apr  6 20:29:49 2015
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 6 Apr 2015 20:29:49 -0700
Subject: [PATCH 10/13] thermal: Make struct thermal_zone_device_ops const
In-Reply-To: <1427385240-6086-11-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-11-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150407032948.GN4648@localhost.localdomain>

On Thu, Mar 26, 2015 at 04:53:57PM +0100, Sascha Hauer wrote:
> Now that the of thermal support no longer changes the
> thermal_zone_device_ops it can be const again.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/thermal_core.c | 2 +-
>  include/linux/thermal.h        | 6 +++---

I believe this change deserves to be done together with the required driver 
updates on those parts that calls this function.

>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index acf00b5..dcdf45e 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -1455,7 +1455,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
>   */
>  struct thermal_zone_device *thermal_zone_device_register(const char *type,
>  	int trips, int mask, void *devdata,
> -	struct thermal_zone_device_ops *ops,
> +	const struct thermal_zone_device_ops *ops,
>  	const struct thermal_zone_params *tzp,
>  	int passive_delay, int polling_delay)
>  {
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 2f77091..ac2897c 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -185,7 +185,7 @@ struct thermal_zone_device {
>  	unsigned long emul_temperature;
>  	int passive;
>  	unsigned int forced_passive;
> -	struct thermal_zone_device_ops *ops;
> +	const struct thermal_zone_device_ops *ops;
>  	const struct thermal_zone_params *tzp;
>  	struct thermal_governor *governor;
>  	struct list_head thermal_instances;
> @@ -317,7 +317,7 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
>  
>  #if IS_ENABLED(CONFIG_THERMAL)
>  struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
> -		void *, struct thermal_zone_device_ops *,
> +		void *, const struct thermal_zone_device_ops *,
>  		const struct thermal_zone_params *, int, int);
>  void thermal_zone_device_unregister(struct thermal_zone_device *);
>  
> @@ -345,7 +345,7 @@ void thermal_notify_framework(struct thermal_zone_device *, int);
>  #else
>  static inline struct thermal_zone_device *thermal_zone_device_register(
>  	const char *type, int trips, int mask, void *devdata,
> -	struct thermal_zone_device_ops *ops,
> +	const struct thermal_zone_device_ops *ops,
>  	const struct thermal_zone_params *tzp,
>  	int passive_delay, int polling_delay)
>  { return ERR_PTR(-ENODEV); }
> -- 
> 2.1.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150406/ca99de30/attachment.sig>

From howard.chen at linaro.org  Tue Apr  7 01:05:05 2015
From: howard.chen at linaro.org (Howard Chen)
Date: Tue,  7 Apr 2015 16:05:05 +0800
Subject: [PATCH v2] ARM: dts: mt8173: support arm64 cpuidle-dt
Message-ID: <1428393905-32166-1-git-send-email-howard.chen@linaro.org>

This patch adds an idle-states node to describe the mt8173 idle states and
also adds references to the idle-states node in all CPU nodes.

Signed-off-by: Howard Chen <howard.chen at linaro.org>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 8554ec3..0d31a34 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -48,6 +48,8 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
 			reg = <0x000>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
 		};
 
 		cpu1: cpu at 1 {
@@ -55,6 +57,7 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x001>;
 			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
 		};
 
 		cpu2: cpu at 100 {
@@ -62,6 +65,7 @@
 			compatible = "arm,cortex-a57";
 			reg = <0x100>;
 			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
 		};
 
 		cpu3: cpu at 101 {
@@ -69,6 +73,19 @@
 			compatible = "arm,cortex-a57";
 			reg = <0x101>;
 			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		idle-states {
+			entry-method = "arm,psci";
+
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x0010000>;
+				entry-latency-us = <639>;
+				exit-latency-us = <328>;
+				min-residency-us = <1088>;
+			};
 		};
 	};
 
-- 
1.9.1



From matthias.bgg at gmail.com  Tue Apr  7 04:47:58 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 7 Apr 2015 13:47:58 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>

Hi Sascha,


2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>
> The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
>
>   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
>
> are available in the git repository at:
>
>   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
>
> for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
>
>   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
>
> ----------------------------------------------------------------
> This patchset contains the initial common clock support for Mediatek SoCs.
> Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> and clock gates.

I tried the patch set on my mt8135 eval board. I used the dts bindings
from a former version of this set [1], but it does not boot the board
(based on v4.0-rc7).
Do you have any hint, what is happening, or are the bindings wrong?

Best regards,
Matthias

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/322813.html


From matthias.bgg at gmail.com  Tue Apr  7 07:01:46 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 7 Apr 2015 16:01:46 +0200
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <CABuKBe+MFHJO8GXRg5KYs2t+j6U4Ynv_hCeW0YQCrS_eZ-fuLA@mail.gmail.com>

2015-03-17 4:13 GMT+01:00 Chaotian Jing <chaotian.jing at mediatek.com>:
> Add Mediatek MMC driver code
>
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  drivers/mmc/host/Kconfig  |    8 +
>  drivers/mmc/host/Makefile |    1 +
>  drivers/mmc/host/mtk-sd.c | 1412 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1421 insertions(+)
>  create mode 100644 drivers/mmc/host/mtk-sd.c
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 61ac63a..8b64377 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -768,3 +768,11 @@ config MMC_TOSHIBA_PCI
>         tristate "Toshiba Type A SD/MMC Card Interface Driver"
>         depends on PCI
>         help
> +
> +config MMC_MTK
> +       tristate "MediaTek SD/MMC Card Interface support"
> +       help
> +         This selects the MediaTek(R) Secure digital and Multimedia card Interface.
> +         If you have a machine with a integrated SD/MMC card reader, say Y or M here.
> +         This is needed if support for any SD/SDIO/MMC devices is required.
> +         If unsure, say N.
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 6a7cfe0..161b3e4 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30)       += sdhci_f_sdh30.o
>  obj-$(CONFIG_MMC_SDHCI_SPEAR)  += sdhci-spear.o
>  obj-$(CONFIG_MMC_WBSD)         += wbsd.o
>  obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
> +obj-$(CONFIG_MMC_MTK)           += mtk-sd.o
>  obj-$(CONFIG_MMC_OMAP)         += omap.o
>  obj-$(CONFIG_MMC_OMAP_HS)      += omap_hsmmc.o
>  obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> new file mode 100644
> index 0000000..86c999b
> --- /dev/null
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -0,0 +1,1412 @@
> +/*
> + * Copyright (c) 2014-2015 MediaTek Inc.
> + * Author: Chaotian.Jing <chaotian.jing at mediatek.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.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/ioport.h>
> +#include <linux/irq.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/spinlock.h>
> +
> +#include <linux/mmc/card.h>
> +#include <linux/mmc/core.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/sd.h>
> +#include <linux/mmc/sdio.h>
> +
> +#define MAX_GPD_NUM         (1 + 1)    /* one null gpd */
> +#define MAX_BD_NUM          1024
> +#define MAX_BD_PER_GPD      MAX_BD_NUM

This looks strange.
Why don't you define MAX_GPD_NUM as two?
Why do you define MAX_BD_PER_GPD when it is the same as MAX_BD_NUM?

Cheers,
Matthias

-- 
motzblog.wordpress.com


From chaotian.jing at mediatek.com  Tue Apr  7 23:39:19 2015
From: chaotian.jing at mediatek.com (chaotian.jing)
Date: Wed, 8 Apr 2015 14:39:19 +0800
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <CABuKBe+MFHJO8GXRg5KYs2t+j6U4Ynv_hCeW0YQCrS_eZ-fuLA@mail.gmail.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CABuKBe+MFHJO8GXRg5KYs2t+j6U4Ynv_hCeW0YQCrS_eZ-fuLA@mail.gmail.com>
Message-ID: <1428475159.15142.3.camel@mhfsdcap03>

Dear Matthias,

Thanks for your review!
Please help to check my comment.
On Tue, 2015-04-07 at 16:01 +0200, Matthias Brugger wrote:
> 2015-03-17 4:13 GMT+01:00 Chaotian Jing <chaotian.jing at mediatek.com>:
> > Add Mediatek MMC driver code
> >
> > Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> > ---
> >  drivers/mmc/host/Kconfig  |    8 +
> >  drivers/mmc/host/Makefile |    1 +
> >  drivers/mmc/host/mtk-sd.c | 1412 +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 1421 insertions(+)
> >  create mode 100644 drivers/mmc/host/mtk-sd.c
> >
> > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> > index 61ac63a..8b64377 100644
> > --- a/drivers/mmc/host/Kconfig
> > +++ b/drivers/mmc/host/Kconfig
> > @@ -768,3 +768,11 @@ config MMC_TOSHIBA_PCI
> >         tristate "Toshiba Type A SD/MMC Card Interface Driver"
> >         depends on PCI
> >         help
> > +
> > +config MMC_MTK
> > +       tristate "MediaTek SD/MMC Card Interface support"
> > +       help
> > +         This selects the MediaTek(R) Secure digital and Multimedia card Interface.
> > +         If you have a machine with a integrated SD/MMC card reader, say Y or M here.
> > +         This is needed if support for any SD/SDIO/MMC devices is required.
> > +         If unsure, say N.
> > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> > index 6a7cfe0..161b3e4 100644
> > --- a/drivers/mmc/host/Makefile
> > +++ b/drivers/mmc/host/Makefile
> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30)       += sdhci_f_sdh30.o
> >  obj-$(CONFIG_MMC_SDHCI_SPEAR)  += sdhci-spear.o
> >  obj-$(CONFIG_MMC_WBSD)         += wbsd.o
> >  obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
> > +obj-$(CONFIG_MMC_MTK)           += mtk-sd.o
> >  obj-$(CONFIG_MMC_OMAP)         += omap.o
> >  obj-$(CONFIG_MMC_OMAP_HS)      += omap_hsmmc.o
> >  obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > new file mode 100644
> > index 0000000..86c999b
> > --- /dev/null
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -0,0 +1,1412 @@
> > +/*
> > + * Copyright (c) 2014-2015 MediaTek Inc.
> > + * Author: Chaotian.Jing <chaotian.jing at mediatek.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.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/ioport.h>
> > +#include <linux/irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_gpio.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/spinlock.h>
> > +
> > +#include <linux/mmc/card.h>
> > +#include <linux/mmc/core.h>
> > +#include <linux/mmc/host.h>
> > +#include <linux/mmc/mmc.h>
> > +#include <linux/mmc/sd.h>
> > +#include <linux/mmc/sdio.h>
> > +
> > +#define MAX_GPD_NUM         (1 + 1)    /* one null gpd */
> > +#define MAX_BD_NUM          1024
> > +#define MAX_BD_PER_GPD      MAX_BD_NUM
> 
> This looks strange.
> Why don't you define MAX_GPD_NUM as two?
> Why do you define MAX_BD_PER_GPD when it is the same as MAX_BD_NUM?
> 
In fact, the second GPD is useless now, I will remove the define of
MAX_GPD_NUM and MAX_BD_PER_GPD.

> Cheers,
> Matthias
> 




From thierry.reding at gmail.com  Wed Apr  8 01:50:16 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Wed,  8 Apr 2015 10:50:16 +0200
Subject: [PATCH] soc/mediatek: Remove unused variables
Message-ID: <1428483016-5472-1-git-send-email-thierry.reding@gmail.com>

From: Thierry Reding <treding at nvidia.com>

The PMIC wrapper driver adds a couple of variables that are never used.
Remove them to avoid build warnings.

Signed-off-by: Thierry Reding <treding at nvidia.com>
---
 drivers/soc/mediatek/mtk-pmic-wrap.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 4a38506154c6..db5be1eec54c 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -563,8 +563,6 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
 
 static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
 {
-	u32 wdata;
-	u32 rdata;
 	unsigned long rate_spi;
 	int ck_mhz;
 
-- 
2.3.2



From matthias.bgg at gmail.com  Wed Apr  8 02:36:28 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Wed, 8 Apr 2015 11:36:28 +0200
Subject: [PATCH] soc/mediatek: Remove unused variables
In-Reply-To: <1428483016-5472-1-git-send-email-thierry.reding@gmail.com>
References: <1428483016-5472-1-git-send-email-thierry.reding@gmail.com>
Message-ID: <CABuKBeKDyBU8WynSKy55XZ7=a2JJzESxO_neKJkKNRTeMKxAqw@mail.gmail.com>

2015-04-08 10:50 GMT+02:00 Thierry Reding <thierry.reding at gmail.com>:
> From: Thierry Reding <treding at nvidia.com>
>
> The PMIC wrapper driver adds a couple of variables that are never used.
> Remove them to avoid build warnings.
>
> Signed-off-by: Thierry Reding <treding at nvidia.com>

You are right, I didn't notice when merging.
Signed-off-by: Matthias Brugger <matthias.bgg at gmail.com>

> ---
>  drivers/soc/mediatek/mtk-pmic-wrap.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
> index 4a38506154c6..db5be1eec54c 100644
> --- a/drivers/soc/mediatek/mtk-pmic-wrap.c
> +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
> @@ -563,8 +563,6 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
>
>  static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
>  {
> -       u32 wdata;
> -       u32 rdata;
>         unsigned long rate_spi;
>         int ck_mhz;
>
> --
> 2.3.2
>



-- 
motzblog.wordpress.com


From ulf.hansson at linaro.org  Wed Apr  8 03:38:56 2015
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 8 Apr 2015 12:38:56 +0200
Subject: =?UTF-8?B?UmU6IOetlOWkjTogW1BBVENIIHYyIDIvNV0gbW1jOiBtZWRpYXRlazogQWRkIE1lZGlhdA==?=
 =?UTF-8?B?ZWsgTU1DIGRyaXZlcg==?=
In-Reply-To: <B077351396223C4F8FE8C4C13672A9CA609795F3@mtkmbs33n1>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
 <B077351396223C4F8FE8C4C13672A9CA609795F3@mtkmbs33n1>
Message-ID: <CAPDyKFrM94E8xXN_q0OqciOHC8WBC+fTOroSnnm+HDTOmWg6Gw@mail.gmail.com>

[...]

>> > +
>> > +struct mt_bdma_desc {
>> > +       u32 first_u32;
>> > +#define BDMA_DESC_EOL          (1 << 0)
>> > +#define BDMA_DESC_CHECKSUM     (0xff << 8) /* bit8 ~ bit15 */
>> > +#define BDMA_DESC_BLKPAD       (1 << 17)
>> > +#define BDMA_DESC_DWPAD                (1 << 18)
>> > +       u32 next;
>> > +       u32 ptr;
>> > +       u32 second_u32;
>> > +#define BDMA_DESC_BUFLEN       (0xffff) /* bit0 ~ bit15 */
>> > +};
>> > +
>> > +struct msdc_dma {
>> > +       struct scatterlist *sg; /* I/O scatter list */
>> > +       struct mt_gpdma_desc *gpd;              /* pointer to gpd
>> array */
>> > +       struct mt_bdma_desc *bd;                /* pointer to bd
>> array */
>> > +       dma_addr_t gpd_addr;    /* the physical address of gpd array */
>> > +       dma_addr_t bd_addr;     /* the physical address of bd array */
>> > +};
>>
>> This looks weird from DMA perspective. Can you elaborate on why you
>> can't use the dmaengine API?
>>
> The gpd and bd structure are determined by the MSDC hw, and, the DMA controller is a part of the MSDC hw, different with the chain dma implemented by the kernel.

Hmm. I haven't reviewed the DMA related parts in detail. I will do
that when you have sent the next version.

>> > +
>> > +struct msdc_host {
>> > +       struct device *dev;
>> > +       struct mmc_host *mmc;   /* mmc structure */
>> > +       int cmd_rsp;
>> > +
>> > +       spinlock_t lock;
>> > +       struct mmc_request *mrq;
>> > +       struct mmc_command *cmd;
>> > +       struct mmc_data *data;
>> > +       int error;
>> > +
>> > +       void __iomem *base;             /* host base address */
>> > +
>> > +       struct msdc_dma dma;    /* dma channel */
>> > +
>> > +       u32 timeout_ns;         /* data timeout ns */
>> > +       u32 timeout_clks;       /* data timeout clks */
>> > +
>> > +       struct pinctrl *pinctrl;
>> > +       struct pinctrl_state *pins_default;
>> > +       struct pinctrl_state *pins_uhs;
>> > +       struct delayed_work req_timeout;
>> > +       int irq;                /* host interrupt */
>> > +
>> > +       struct clk *src_clk;    /* msdc source clock */
>> > +       u32 mclk;               /* mmc subsystem clock */
>> > +       u32 hclk;               /* host clock speed */
>> > +       u32 sclk;               /* SD/MS clock speed */
>> > +       bool ddr;
>> > +};
>> > +
>> > +static void sdr_set_bits(void __iomem *reg, u32 bs)
>> > +{
>> > +       u32 val = readl(reg);
>> > +
>> > +       val |= bs;
>> > +       writel(val, reg);
>> > +}
>> > +
>> > +static void sdr_clr_bits(void __iomem *reg, u32 bs)
>> > +{
>> > +       u32 val = readl(reg);
>> > +
>> > +       val &= ~(u32)bs;
>> > +       writel(val, reg);
>> > +}
>> > +
>> > +static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
>> > +{
>> > +       unsigned int tv = readl(reg);
>> > +
>> > +       tv &= ~field;
>> > +       tv |= ((val) << (ffs((unsigned int)field) - 1));
>> > +       writel(tv, reg);
>> > +}
>>
>> A common thought for all the three above functions:
>>
>> Have you considered using a cache variable for those registers that
>> often gets updated? In that way you would have to read the register
>> value every time when you want to write to it. It should improve
>> performance a bit.
>>
> These register can be modified by the MSDC hw, cannot cache it.

Is that true for all registers?

Anyway, let's leave this as is.

>> > +
>> > +static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
>> > +{
>> > +       unsigned int tv = readl(reg);
>> > +
>> > +       *val = ((tv & field) >> (ffs((unsigned int)field) - 1));
>> > +}
>> > +
>> > +static void msdc_reset_hw(struct msdc_host *host)
>> > +{
>> > +       u32 val;
>> > +
>> > +       sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
>> > +       while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
>> > +               cpu_relax();
>> > +
>> > +       sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
>> > +       while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
>> > +               cpu_relax();
>> > +
>> > +       val = readl(host->base + MSDC_INT);
>> > +       writel(val, host->base + MSDC_INT);
>> > +}
>> > +
>> > +static void msdc_cmd_next(struct msdc_host *host,
>> > +               struct mmc_request *mrq, struct mmc_command *cmd);
>>
>> Please investigate whether you can move around the code to prevent
>> this static declaration of the function.
>>
> It is hard to do it, because the first cmd may be CMD23, and do the next is send the mrq->cmd, so, there is a loop here, at least on method need do static declaration,

Okay.

[...]

>> > +/* clock control primitives */
>> > +static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
>> > +{
>> > +       u32 timeout, clk_ns;
>> > +       u32 mode = 0;
>> > +
>> > +       host->timeout_ns = ns;
>> > +       host->timeout_clks = clks;
>> > +       if (host->sclk == 0) {
>> > +               timeout = 0;
>> > +       } else {
>> > +               clk_ns  = 1000000000UL / host->sclk;
>> > +               timeout = (ns + clk_ns - 1) / clk_ns + clks;
>> > +               /* in 1048576 sclk cycle unit */
>> > +               timeout = (timeout + (1 << 20) - 1) >> 20;
>> > +               sdr_get_field(host->base + MSDC_CFG,
>> MSDC_CFG_CKMOD, &mode);
>> > +               /*DDR mode will double the clk cycles for data timeout */
>>
>> How do you know you will be using DDR at this point? Don't you need to
>> check for that?
>>
> The MSDC_CFG_CKMODE can show current mode(DDR or SDR).

Ah, thanks. Got it.

[...]

>> > +static void msdc_request_done(struct msdc_host *host, struct
>> mmc_request *mrq)
>> > +{
>> > +       unsigned long flags;
>> > +
>> > +       spin_lock_irqsave(&host->lock, flags);
>> > +       cancel_delayed_work(&host->req_timeout);
>>
>> This looks racy.
>>
>> Don't you need a cancel_delayed_work_sync() from somewhere, to be sure
>> that work isn't preemted after the "host->mrq" has been reset here? Or
>> maybe there is another way!? Of course that can't be done with the
>> spin_locks held, but I asume you get my point.
> Yes, I get your point, actually, we set a 5s timeout for each request, and, if the work already pending(means that some error happens), we do not wait it,
> And the work will set the event to timeout and return,
> So, maybe a good solution is that need check the return value of the cancel_delayed_work(), if it is pending, directly return, and do not set the host->mrq to 0 to avoid the race condition,

That should work.

[...]

>>
>> "ocr_avail" should be fetched from the vmmc regulator, when you invoke
>> mmc_regulator_get_supply() above.
> Yes, I also want to remove it, but, Not all devices use regulator, our SDIO device which connected on MSDC3, it's power is controlled by gpio.
> This because the regulator of the PMU is not enough.

So could you perhaps use a "gpio regulator" for this GPIO pin? There
is already support to easily describe such in DT.

Or it is a "reset GPIO" you are talking about?

[...]

Kind regards
Uffe


From lorenzo.pieralisi at arm.com  Wed Apr  8 03:54:43 2015
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Wed, 8 Apr 2015 11:54:43 +0100
Subject: [PATCH v2] ARM: dts: mt8173: support arm64 cpuidle-dt
In-Reply-To: <1428393905-32166-1-git-send-email-howard.chen@linaro.org>
References: <1428393905-32166-1-git-send-email-howard.chen@linaro.org>
Message-ID: <20150408105443.GA23642@red-moon>

On Tue, Apr 07, 2015 at 09:05:05AM +0100, Howard Chen wrote:
> This patch adds an idle-states node to describe the mt8173 idle states and
> also adds references to the idle-states node in all CPU nodes.
> 
> Signed-off-by: Howard Chen <howard.chen at linaro.org>

Is copying me in too much effort to ask ?

>  arch/arm64/boot/dts/mediatek/mt8173.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> index 8554ec3..0d31a34 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> @@ -48,6 +48,8 @@
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a53";
>  			reg = <0x000>;
> +			enable-method = "psci";
> +			cpu-idle-states = <&CPU_SLEEP_0>;

Cluster idle state vanished between v1 and v2.

?

>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -55,6 +57,7 @@
>  			compatible = "arm,cortex-a53";
>  			reg = <0x001>;
>  			enable-method = "psci";
> +			cpu-idle-states = <&CPU_SLEEP_0>;
>  		};
>  
>  		cpu2: cpu at 100 {
> @@ -62,6 +65,7 @@
>  			compatible = "arm,cortex-a57";
>  			reg = <0x100>;
>  			enable-method = "psci";
> +			cpu-idle-states = <&CPU_SLEEP_0>;
>  		};
>  
>  		cpu3: cpu at 101 {
> @@ -69,6 +73,19 @@
>  			compatible = "arm,cortex-a57";
>  			reg = <0x101>;
>  			enable-method = "psci";
> +			cpu-idle-states = <&CPU_SLEEP_0>;
> +		};
> +
> +		idle-states {
> +			entry-method = "arm,psci";
> +
> +			CPU_SLEEP_0: cpu-sleep-0 {
> +				compatible = "arm,idle-state";
> +				arm,psci-suspend-param = <0x0010000>;
> +				entry-latency-us = <639>;
> +				exit-latency-us = <328>;
> +				min-residency-us = <1088>;
> +			};
>  		};
>  	};

Is the arch timer still running when you enter this state ?

Apart from these remarks the patch seems fine, I wonder whether we should
merge these changes into the kernel instead of keeping these changes in
firmware for specific kernel configurations.

Lorenzo


From k.kozlowski at samsung.com  Thu Apr  9 00:27:47 2015
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 9 Apr 2015 09:27:47 +0200
Subject: [PATCH 1/6] clk: make strings in parent name arrays const
In-Reply-To: <1427825817-26773-2-git-send-email-s.hauer@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <1427825817-26773-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CAJKOXPeNw6teVhgnuW3da=chMemCErTWK_oV4rx=CBaHjyTQ7w@mail.gmail.com>

2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> The clk functions and structs declare the parent_name arrays as
> 'const char **parent_names' which means the parent name strings
> are const, but the array itself is not. Use
> 'const char * const * parent_names' instead which also makes
> the array const. This allows us to put the parent_name arrays into
> the __initconst section.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

and tested:
Tested-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>


Best regards,
Krzysztof


From matthias.bgg at gmail.com  Thu Apr  9 10:03:57 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 9 Apr 2015 19:03:57 +0200
Subject: [PATCH 2/6] clk: mediatek: Add initial common clock support for
 Mediatek SoCs.
In-Reply-To: <1427825817-26773-3-git-send-email-s.hauer@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <1427825817-26773-3-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeL=jM5ce+2RLF8QVdbXgqjmgS7Uzc1QVzjoHPWq3g+NPQ@mail.gmail.com>

2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> From: James Liao <jamesjj.liao at mediatek.com>
>
> This patch adds common clock support for Mediatek SoCs, including plls,
> muxes and clock gates.
>
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/clk/Makefile            |   1 +
>  drivers/clk/mediatek/Makefile   |   1 +
>  drivers/clk/mediatek/clk-gate.c | 137 ++++++++++++++++
>  drivers/clk/mediatek/clk-gate.h |  49 ++++++
>  drivers/clk/mediatek/clk-mtk.c  | 197 +++++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.h  | 155 +++++++++++++++++++
>  drivers/clk/mediatek/clk-pll.c  | 335 ++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 875 insertions(+)
>  create mode 100644 drivers/clk/mediatek/Makefile
>  create mode 100644 drivers/clk/mediatek/clk-gate.c
>  create mode 100644 drivers/clk/mediatek/clk-gate.h
>  create mode 100644 drivers/clk/mediatek/clk-mtk.c
>  create mode 100644 drivers/clk/mediatek/clk-mtk.h
>  create mode 100644 drivers/clk/mediatek/clk-pll.c
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index d478ceb..6d97203 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -49,6 +49,7 @@ obj-$(CONFIG_ARCH_HI3xxx)             += hisilicon/
>  obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>  obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
> +obj-$(CONFIG_ARCH_MEDIATEK)            += mediatek/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>  endif
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> new file mode 100644
> index 0000000..c384e97
> --- /dev/null
> +++ b/drivers/clk/mediatek/Makefile
> @@ -0,0 +1 @@
> +obj-y += clk-mtk.o clk-pll.o clk-gate.o
> diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
> new file mode 100644
> index 0000000..9d77ee3
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-gate.c
> @@ -0,0 +1,137 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/clkdev.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
> +{
> +       struct mtk_clk_gate *cg = to_clk_gate(hw);
> +       u32 val;
> +
> +       regmap_read(cg->regmap, cg->sta_ofs, &val);
> +
> +       val &= BIT(cg->bit);
> +
> +       return val == 0;
> +}
> +
> +static int mtk_cg_bit_is_set(struct clk_hw *hw)
> +{
> +       struct mtk_clk_gate *cg = to_clk_gate(hw);
> +       u32 val;
> +
> +       regmap_read(cg->regmap, cg->sta_ofs, &val);
> +
> +       val &= BIT(cg->bit);
> +
> +       return val != 0;
> +}
> +
> +static void mtk_cg_set_bit(struct clk_hw *hw)
> +{
> +       struct mtk_clk_gate *cg = to_clk_gate(hw);
> +
> +       regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
> +}
> +
> +static void mtk_cg_clr_bit(struct clk_hw *hw)
> +{
> +       struct mtk_clk_gate *cg = to_clk_gate(hw);
> +
> +       regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
> +}
> +
> +static int mtk_cg_enable(struct clk_hw *hw)
> +{
> +       mtk_cg_clr_bit(hw);
> +
> +       return 0;
> +}
> +
> +static void mtk_cg_disable(struct clk_hw *hw)
> +{
> +       mtk_cg_set_bit(hw);
> +}
> +
> +static int mtk_cg_enable_inv(struct clk_hw *hw)
> +{
> +       mtk_cg_set_bit(hw);
> +
> +       return 0;
> +}
> +
> +static void mtk_cg_disable_inv(struct clk_hw *hw)
> +{
> +       mtk_cg_clr_bit(hw);
> +}
> +
> +const struct clk_ops mtk_clk_gate_ops_setclr = {
> +       .is_enabled     = mtk_cg_bit_is_cleared,
> +       .enable         = mtk_cg_enable,
> +       .disable        = mtk_cg_disable,
> +};
> +
> +const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
> +       .is_enabled     = mtk_cg_bit_is_set,
> +       .enable         = mtk_cg_enable_inv,
> +       .disable        = mtk_cg_disable_inv,
> +};
> +
> +struct clk *mtk_clk_register_gate(
> +               const char *name,
> +               const char *parent_name,
> +               struct regmap *regmap,
> +               int set_ofs,
> +               int clr_ofs,
> +               int sta_ofs,
> +               u8 bit,
> +               const struct clk_ops *ops)
> +{
> +       struct mtk_clk_gate *cg;
> +       struct clk *clk;
> +       struct clk_init_data init;
> +
> +       cg = kzalloc(sizeof(*cg), GFP_KERNEL);
> +       if (!cg)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.flags = CLK_SET_RATE_PARENT;
> +       init.parent_names = parent_name ? &parent_name : NULL;
> +       init.num_parents = parent_name ? 1 : 0;
> +       init.ops = ops;
> +
> +       cg->regmap = regmap;
> +       cg->set_ofs = set_ofs;
> +       cg->clr_ofs = clr_ofs;
> +       cg->sta_ofs = sta_ofs;
> +       cg->bit = bit;
> +
> +       cg->hw.init = &init;
> +
> +       clk = clk_register(NULL, &cg->hw);
> +       if (IS_ERR(clk))
> +               kfree(cg);
> +
> +       return clk;
> +}
> diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
> new file mode 100644
> index 0000000..6b6780b
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-gate.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#ifndef __DRV_CLK_GATE_H
> +#define __DRV_CLK_GATE_H
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +struct mtk_clk_gate {
> +       struct clk_hw   hw;
> +       struct regmap   *regmap;
> +       int             set_ofs;
> +       int             clr_ofs;
> +       int             sta_ofs;
> +       u8              bit;
> +};
> +
> +static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct mtk_clk_gate, hw);
> +}
> +
> +extern const struct clk_ops mtk_clk_gate_ops_setclr;
> +extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
> +
> +struct clk *mtk_clk_register_gate(
> +               const char *name,
> +               const char *parent_name,
> +               struct regmap *regmap,
> +               int set_ofs,
> +               int clr_ofs,
> +               int sta_ofs,
> +               u8 bit,
> +               const struct clk_ops *ops);
> +
> +#endif /* __DRV_CLK_GATE_H */
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> new file mode 100644
> index 0000000..746bb34
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -0,0 +1,197 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/clkdev.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
> +{
> +       int i;
> +       struct clk_onecell_data *clk_data;
> +
> +       clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +       if (!clk_data)
> +               return NULL;
> +
> +       clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
> +       if (!clk_data->clks)
> +               goto err_out;
> +
> +       clk_data->clk_num = clk_num;
> +
> +       for (i = 0; i < clk_num; i++)
> +               clk_data->clks[i] = ERR_PTR(-ENOENT);
> +
> +       return clk_data;
> +err_out:
> +       kfree(clk_data);
> +
> +       return NULL;
> +}
> +
> +void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
> +               struct clk_onecell_data *clk_data)
> +{
> +       int i;
> +       struct clk *clk;
> +
> +       for (i = 0; i < num; i++) {
> +               const struct mtk_fixed_factor *ff = &clks[i];
> +
> +               clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
> +                               CLK_SET_RATE_PARENT, ff->mult, ff->div);
> +
> +               if (IS_ERR(clk)) {
> +                       pr_err("Failed to register clk %s: %ld\n",
> +                                       ff->name, PTR_ERR(clk));
> +                       continue;
> +               }
> +
> +               if (clk_data)
> +                       clk_data->clks[ff->id] = clk;
> +       }
> +}
> +
> +int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
> +               int num, struct clk_onecell_data *clk_data)
> +{
> +       int i;
> +       struct clk *clk;
> +       struct regmap *regmap;
> +
> +       if (!clk_data)
> +               return -ENOMEM;
> +
> +       regmap = syscon_node_to_regmap(node);
> +       if (IS_ERR(regmap)) {
> +               pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
> +                               PTR_ERR(regmap));
> +               return PTR_ERR(regmap);
> +       }
> +
> +       for (i = 0; i < num; i++) {
> +               const struct mtk_gate *gate = &clks[i];
> +
> +               clk = mtk_clk_register_gate(gate->name, gate->parent_name,
> +                               regmap,
> +                               gate->regs->set_ofs,
> +                               gate->regs->clr_ofs,
> +                               gate->regs->sta_ofs,
> +                               gate->shift, gate->ops);
> +
> +               if (IS_ERR(clk)) {
> +                       pr_err("Failed to register clk %s: %ld\n",
> +                                       gate->name, PTR_ERR(clk));
> +                       continue;
> +               }
> +
> +               clk_data->clks[gate->id] = clk;
> +       }
> +
> +       return 0;
> +}
> +
> +struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> +               void __iomem *base, spinlock_t *lock)
> +{
> +       struct clk *clk;
> +       struct clk_mux *mux = NULL;
> +       struct clk_gate *gate = NULL;
> +       struct clk_divider *div = NULL;
> +       struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
> +       const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
> +       const char * const *parent_names;
> +       const char *parent;
> +       int num_parents;
> +       int ret;
> +
> +       if (mc->mux_shift >= 0) {
> +               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> +               if (!mux)
> +                       return ERR_PTR(-ENOMEM);
> +
> +               mux->reg = base + mc->mux_reg;
> +               mux->mask = BIT(mc->mux_width) - 1;
> +               mux->shift = mc->mux_shift;
> +               mux->lock = lock;
> +
> +               mux_hw = &mux->hw;
> +               mux_ops = &clk_mux_ops;
> +
> +               parent_names = mc->parent_names;
> +               num_parents = mc->num_parents;
> +       } else {
> +               parent = mc->parent;
> +               parent_names = &parent;
> +               num_parents = 1;
> +       }
> +
> +       if (mc->gate_shift >= 0) {
> +               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +               if (!gate) {
> +                       ret = -ENOMEM;
> +                       goto err_out;
> +               }
> +
> +               gate->reg = base + mc->gate_reg;
> +               gate->bit_idx = mc->gate_shift;
> +               gate->flags = CLK_GATE_SET_TO_DISABLE;
> +               gate->lock = lock;
> +
> +               gate_hw = &gate->hw;
> +               gate_ops = &clk_gate_ops;
> +       }
> +
> +       if (mc->divider_shift >= 0) {
> +               div = kzalloc(sizeof(*div), GFP_KERNEL);
> +               if (!div) {
> +                       ret = -ENOMEM;
> +                       goto err_out;
> +               }
> +
> +               div->reg = base + mc->divider_reg;
> +               div->shift = mc->divider_shift;
> +               div->width = mc->divider_width;
> +               div->lock = lock;
> +
> +               div_hw = &div->hw;
> +               div_ops = &clk_divider_ops;
> +       }
> +
> +       clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
> +               mux_hw, mux_ops,
> +               div_hw, div_ops,
> +               gate_hw, gate_ops,
> +               mc->flags);
> +
> +       if (IS_ERR(clk)) {
> +               kfree(gate);
> +               kfree(mux);
> +       }
> +
> +       return clk;
> +err_out:
> +       kfree(mux);
> +
> +       return ERR_PTR(ret);
> +}
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> new file mode 100644
> index 0000000..5aaba81
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -0,0 +1,155 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#ifndef __DRV_CLK_MTK_H
> +#define __DRV_CLK_MTK_H
> +
> +#include <linux/regmap.h>
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +#define MAX_MUX_GATE_BIT       31
> +#define INVALID_MUX_GATE_BIT   (MAX_MUX_GATE_BIT + 1)
> +
> +#define MHZ (1000 * 1000)
> +
> +struct mtk_fixed_factor {
> +       int id;
> +       const char *name;
> +       const char *parent_name;
> +       int mult;
> +       int div;
> +};
> +
> +#define FACTOR(_id, _name, _parent, _mult, _div) {     \
> +               .id = _id,                              \
> +               .name = _name,                          \
> +               .parent_name = _parent,                 \
> +               .mult = _mult,                          \
> +               .div = _div,                            \
> +       }
> +
> +extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
> +               int num, struct clk_onecell_data *clk_data);
> +
> +struct mtk_composite {
> +       int id;
> +       const char *name;
> +       const char * const * parent_names;
> +       const char *parent;
> +       unsigned flags;
> +
> +       uint32_t mux_reg;
> +       uint32_t divider_reg;
> +       uint32_t gate_reg;
> +
> +       signed char mux_shift;
> +       signed char mux_width;
> +       signed char gate_shift;
> +
> +       signed char divider_shift;
> +       signed char divider_width;
> +
> +       signed char num_parents;
> +};
> +
> +#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {  \
> +               .id = _id,                                              \
> +               .name = _name,                                          \
> +               .mux_reg = _reg,                                        \
> +               .mux_shift = _shift,                                    \
> +               .mux_width = _width,                                    \
> +               .gate_reg = _reg,                                       \
> +               .gate_shift = _gate,                                    \
> +               .divider_shift = -1,                                    \
> +               .parent_names = _parents,                               \
> +               .num_parents = ARRAY_SIZE(_parents),                    \
> +               .flags = CLK_SET_RATE_PARENT,                           \
> +       }
> +
> +#define MUX(_id, _name, _parents, _reg, _shift, _width) {              \
> +               .id = _id,                                              \
> +               .name = _name,                                          \
> +               .mux_reg = _reg,                                        \
> +               .mux_shift = _shift,                                    \
> +               .mux_width = _width,                                    \
> +               .gate_shift = -1,                                       \
> +               .divider_shift = -1,                                    \
> +               .parent_names = _parents,                               \
> +               .num_parents = ARRAY_SIZE(_parents),                    \
> +               .flags = CLK_SET_RATE_PARENT,                           \
> +       }
> +
> +#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {      \
> +               .id = _id,                                              \
> +               .parent = _parent,                                      \
> +               .name = _name,                                          \
> +               .divider_reg = _div_reg,                                \
> +               .divider_shift = _div_shift,                            \
> +               .divider_width = _div_width,                            \
> +               .gate_reg = _gate_reg,                                  \
> +               .gate_shift = _gate_shift,                              \
> +               .mux_shift = -1,                                        \
> +               .flags = 0,                                             \
> +       }
> +
> +struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> +               void __iomem *base, spinlock_t *lock);
> +
> +struct mtk_gate_regs {
> +       u32 sta_ofs;
> +       u32 clr_ofs;
> +       u32 set_ofs;
> +};
> +
> +struct mtk_gate {
> +       int id;
> +       const char *name;
> +       const char *parent_name;
> +       const struct mtk_gate_regs *regs;
> +       int shift;
> +       const struct clk_ops *ops;
> +};
> +
> +int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
> +               int num, struct clk_onecell_data *clk_data);
> +
> +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
> +
> +#define HAVE_RST_BAR   BIT(0)
> +
> +struct mtk_pll_data {
> +       int id;
> +       const char *name;
> +       uint32_t reg;
> +       uint32_t pwr_reg;
> +       uint32_t en_mask;
> +       uint32_t pd_reg;
> +       uint32_t tuner_reg;
> +       int pd_shift;
> +       unsigned int flags;
> +       const struct clk_ops *ops;
> +       u32 rst_bar_mask;
> +       unsigned long fmax;
> +       int pcwbits;
> +       uint32_t pcw_reg;
> +       int pcw_shift;
> +};
> +
> +void __init mtk_clk_register_plls(struct device_node *node,
> +               const struct mtk_pll_data *plls, int num_plls,
> +               struct clk_onecell_data *clk_data);
> +
> +#endif /* __DRV_CLK_MTK_H */
> diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
> new file mode 100644
> index 0000000..3ef6b21
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-pll.c
> @@ -0,0 +1,335 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/clkdev.h>
> +#include <linux/delay.h>
> +
> +#include "clk-mtk.h"
> +
> +#define REG_CON0               0
> +#define REG_CON1               4
> +
> +#define CON0_BASE_EN           BIT(0)
> +#define CON0_PWR_ON            BIT(0)
> +#define CON0_ISO_EN            BIT(1)
> +#define CON0_PCW_CHG           BIT(31)
> +
> +#define AUDPLL_TUNER_EN                BIT(31)
> +
> +#define POSTDIV_MASK           0x7
> +#define INTEGER_BITS           7
> +
> +/*
> + * MediaTek PLLs are configured through their pcw value. The pcw value describes
> + * a divider in the PLL feedback loop which consists of 7 bits for the integer
> + * part and the remaining bits (if present) for the fractional part. Also they
> + * have a 3 bit power-of-two post divider.
> + */
> +
> +struct mtk_clk_pll {
> +       struct clk_hw   hw;
> +       void __iomem    *base_addr;
> +       void __iomem    *pd_addr;
> +       void __iomem    *pwr_addr;
> +       void __iomem    *tuner_addr;
> +       void __iomem    *pcw_addr;
> +       const struct mtk_pll_data *data;
> +};
> +
> +static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct mtk_clk_pll, hw);
> +}
> +
> +static int mtk_pll_is_prepared(struct clk_hw *hw)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +
> +       return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
> +}
> +
> +static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
> +               u32 pcw, int postdiv)
> +{
> +       int pcwbits = pll->data->pcwbits;
> +       int pcwfbits;
> +       u64 vco;
> +       u8 c = 0;
> +
> +       /* The fractional part of the PLL divider. */
> +       pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
> +
> +       vco = (u64)fin * pcw;
> +
> +       if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
> +               c = 1;
> +
> +       vco >>= pcwfbits;
> +
> +       if (c)
> +               vco++;
> +
> +       return ((unsigned long)vco + postdiv - 1) / postdiv;
> +}
> +
> +static void mtk_pll_set_rate_regs(struct clk_hw *hw, u32 pcw,
> +               int postdiv)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);

>From mtk_pll_set_rate we can pass a pointer to mtk_clk_pll instead of clk_hw.

> +       u32 con1, pd, val;
> +       int pll_en;
> +
> +       /* set postdiv */
> +       pd = readl(pll->pd_addr);
> +       pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
> +       pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
> +       writel(pd, pll->pd_addr);
> +
> +       pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
> +
> +       /* set pcw */
> +       val = readl(pll->pcw_addr);
> +
> +       val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
> +                       pll->data->pcw_shift);
> +       val |= pcw << pll->data->pcw_shift;
> +       writel(val, pll->pcw_addr);
> +
> +       con1 = readl(pll->base_addr + REG_CON1);
> +
> +       if (pll_en)
> +               con1 |= CON0_PCW_CHG;
> +
> +       writel(con1, pll->base_addr + REG_CON1);
> +       if (pll->tuner_addr)
> +               writel(con1 + 1, pll->tuner_addr);
> +
> +       if (pll_en)
> +               usleep_range(20, 1000);
> +}
> +
> +/*
> + * mtk_pll_calc_values - calculate good values for a given input frequency.
> + * @pll:       The pll
> + * @pcw:       The pcw value (output)
> + * @postdiv:   The post divider (output)
> + * @freq:      The desired target frequency
> + * @fin:       The input frequency
> + *
> + */
> +static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
> +               u32 freq, u32 fin)
> +{
> +       unsigned long fmin = 1000 * MHZ;
> +       u64 _pcw;
> +       u32 val;
> +
> +       if (freq > pll->data->fmax)
> +               freq = pll->data->fmax;
> +
> +       for (val = 0; val < 4; val++) {
> +               *postdiv = 1 << val;
> +               if (freq * *postdiv >= fmin)
> +                       break;
> +       }
> +
> +       /* _pcw = freq * postdiv / fin * 2^pcwfbits */
> +       _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
> +       do_div(_pcw, fin);
> +
> +       *pcw = (u32)_pcw;
> +}
> +
> +static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +               unsigned long parent_rate)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +       u32 pcw = 0;
> +       u32 postdiv;
> +
> +       mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
> +       mtk_pll_set_rate_regs(hw, pcw, postdiv);
> +
> +       return 0;
> +}
> +
> +static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
> +               unsigned long parent_rate)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +       u32 postdiv;
> +       u32 pcw;
> +
> +       postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
> +       postdiv = 1 << postdiv;
> +
> +       pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
> +       pcw &= GENMASK(pll->data->pcwbits - 1, 0);
> +
> +       return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
> +}
> +
> +static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +               unsigned long *prate)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +       u32 pcw = 0;
> +       int postdiv;
> +
> +       mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
> +
> +       return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
> +}
> +
> +static int mtk_pll_prepare(struct clk_hw *hw)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +       u32 r;
> +
> +       r = readl(pll->pwr_addr) | CON0_PWR_ON;
> +       writel(r, pll->pwr_addr);
> +       usleep_range(1, 100);
> +
> +       r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
> +       writel(r, pll->pwr_addr);
> +       usleep_range(1, 100);
> +
> +       r = readl(pll->base_addr + REG_CON0);
> +       r |= pll->data->en_mask;
> +       writel(r, pll->base_addr + REG_CON0);
> +
> +       if (pll->tuner_addr) {
> +               r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
> +               writel(r, pll->tuner_addr);
> +       }
> +
> +       usleep_range(20, 1000);
> +
> +       if (pll->data->flags & HAVE_RST_BAR) {
> +               r = readl(pll->base_addr + REG_CON0);
> +               r |= pll->data->rst_bar_mask;
> +               writel(r, pll->base_addr + REG_CON0);
> +       }
> +
> +       return 0;
> +}
> +
> +static void mtk_pll_unprepare(struct clk_hw *hw)
> +{
> +       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
> +       u32 r;
> +
> +       if (pll->data->flags & HAVE_RST_BAR) {
> +               r = readl(pll->base_addr + REG_CON0);
> +               r &= ~pll->data->rst_bar_mask;
> +               writel(r, pll->base_addr + REG_CON0);
> +       }
> +
> +       if (pll->tuner_addr) {
> +               r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
> +               writel(r, pll->tuner_addr);
> +       }
> +
> +       r = readl(pll->base_addr + REG_CON0);
> +       r &= ~CON0_BASE_EN;
> +       writel(r, pll->base_addr + REG_CON0);
> +
> +       r = readl(pll->pwr_addr) | CON0_ISO_EN;
> +       writel(r, pll->pwr_addr);
> +
> +       r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
> +       writel(r, pll->pwr_addr);
> +}
> +
> +static const struct clk_ops mtk_pll_ops = {
> +       .is_prepared    = mtk_pll_is_prepared,
> +       .prepare        = mtk_pll_prepare,
> +       .unprepare      = mtk_pll_unprepare,
> +       .recalc_rate    = mtk_pll_recalc_rate,
> +       .round_rate     = mtk_pll_round_rate,
> +       .set_rate       = mtk_pll_set_rate,
> +};
> +
> +static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
> +               void __iomem *base)
> +{
> +       struct mtk_clk_pll *pll;
> +       struct clk_init_data init;
> +       struct clk *clk;
> +       const char *parent_name = "clk26m";
> +
> +       pr_debug("%s(): name: %s\n", __func__, data->name);

Please please make this more descriptive or delete the debug message.

> +
> +       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +       if (!pll)
> +               return ERR_PTR(-ENOMEM);
> +
> +       pll->base_addr = base + data->reg;
> +       pll->pwr_addr = base + data->pwr_reg;
> +       pll->pd_addr = base + data->pd_reg;
> +       pll->pcw_addr = base + data->pcw_reg;
> +       if (data->tuner_reg)
> +               pll->tuner_addr = base + data->tuner_reg;
> +       pll->hw.init = &init;
> +       pll->data = data;
> +
> +       init.name = data->name;
> +       init.ops = &mtk_pll_ops;
> +       init.parent_names = &parent_name;
> +       init.num_parents = 1;
> +
> +       clk = clk_register(NULL, &pll->hw);
> +
> +       if (IS_ERR(clk))
> +               kfree(pll);
> +
> +       return clk;
> +}
> +
> +void __init mtk_clk_register_plls(struct device_node *node,
> +               const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
> +{
> +       void __iomem *base;
> +       int r, i;
> +       struct clk *clk;
> +
> +       base = of_iomap(node, 0);
> +       if (!base) {
> +               pr_err("%s(): ioremap failed\n", __func__);
> +               return;
> +       }
> +
> +       for (i = 0; i < num_plls; i++) {
> +               const struct mtk_pll_data *pll = &plls[i];
> +
> +               clk = mtk_clk_register_pll(pll, base);
> +
> +               if (IS_ERR(clk)) {
> +                       pr_err("Failed to register clk %s: %ld\n",
> +                                       pll->name, PTR_ERR(clk));
> +                       continue;
> +               }
> +
> +               clk_data->clks[pll->id] = clk;
> +       }
> +
> +       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +       if (r)
> +               pr_err("%s(): could not register clock provider: %d\n",
> +                       __func__, r);
> +}
> --
> 2.1.4
>



-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Thu Apr  9 10:05:22 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 9 Apr 2015 19:05:22 +0200
Subject: [PATCH 4/6] clk: mediatek: Add basic clocks for Mediatek MT8135.
In-Reply-To: <1427825817-26773-5-git-send-email-s.hauer@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <1427825817-26773-5-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeJKrDMR+xHSk_WvppGE7KftMy-QL8ATFi081++C3vaKEg@mail.gmail.com>

2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> From: James Liao <jamesjj.liao at mediatek.com>
>
> This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
> INFRA and PERI clocks.
>
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/clk/mediatek/Makefile                      |   1 +
>  drivers/clk/mediatek/clk-mt8135.c                  | 640 +++++++++++++++++++++
>  include/dt-bindings/clock/mt8135-clk.h             | 190 ++++++
>  .../dt-bindings/reset-controller/mt8135-resets.h   |  64 +++
>  4 files changed, 895 insertions(+)
>  create mode 100644 drivers/clk/mediatek/clk-mt8135.c
>  create mode 100644 include/dt-bindings/clock/mt8135-clk.h
>  create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h
>
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> index 0b6f1c3..12ce576 100644
> --- a/drivers/clk/mediatek/Makefile
> +++ b/drivers/clk/mediatek/Makefile
> @@ -1,2 +1,3 @@
>  obj-y += clk-mtk.o clk-pll.o clk-gate.o
>  obj-$(CONFIG_RESET_CONTROLLER) += reset.o
> +obj-y += clk-mt8135.o
> diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
> new file mode 100644
> index 0000000..a08f2fe
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt8135.c
> @@ -0,0 +1,640 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/syscon.h>
> +#include <dt-bindings/clock/mt8135-clk.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +static DEFINE_SPINLOCK(mt8135_clk_lock);
> +
> +static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
> +       FACTOR(TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
> +       FACTOR(TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
> +       FACTOR(TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
> +       FACTOR(TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
> +};
> +
> +static const struct mtk_fixed_factor top_divs[] __initconst = {
> +       FACTOR(TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
> +       FACTOR(TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
> +       FACTOR(TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
> +       FACTOR(TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
> +
> +       FACTOR(TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
> +       FACTOR(TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
> +       FACTOR(TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
> +       FACTOR(TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
> +       FACTOR(TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
> +
> +       FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
> +       FACTOR(TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
> +       FACTOR(TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
> +       FACTOR(TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
> +       FACTOR(TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
> +       FACTOR(TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
> +
> +       FACTOR(TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
> +       FACTOR(TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
> +       FACTOR(TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
> +       FACTOR(TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
> +       FACTOR(TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
> +       FACTOR(TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
> +       FACTOR(TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
> +       FACTOR(TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
> +
> +       FACTOR(TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
> +
> +       FACTOR(TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
> +       FACTOR(TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
> +
> +       FACTOR(TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
> +
> +       FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
> +       FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
> +       FACTOR(TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
> +       FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
> +       FACTOR(TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
> +
> +       FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
> +       FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
> +       FACTOR(TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
> +       FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
> +
> +       FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
> +       FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
> +       FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
> +       FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 5),

shouldn't that be
FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
as univpll_249p6m is univpll divided by 5?


From chaotian.jing at mediatek.com  Thu Apr  9 20:17:20 2015
From: chaotian.jing at mediatek.com (chaotian.jing)
Date: Fri, 10 Apr 2015 11:17:20 +0800
Subject: =?UTF-8?Q?=E7=AD=94=E5=A4=8D=3A?= [PATCH v2 2/5] mmc: mediatek:
 Add Mediatek MMC driver
In-Reply-To: <CAPDyKFrM94E8xXN_q0OqciOHC8WBC+fTOroSnnm+HDTOmWg6Gw@mail.gmail.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
 <B077351396223C4F8FE8C4C13672A9CA609795F3@mtkmbs33n1>
 <CAPDyKFrM94E8xXN_q0OqciOHC8WBC+fTOroSnnm+HDTOmWg6Gw@mail.gmail.com>
Message-ID: <1428635840.16027.1.camel@mhfsdcap03>

Dear Ulf,

Thanks!
please help to check my comment:

On Wed, 2015-04-08 at 12:38 +0200, Ulf Hansson wrote:
> [...]
> 
> >> > +
> >> > +struct mt_bdma_desc {
> >> > +       u32 first_u32;
> >> > +#define BDMA_DESC_EOL          (1 << 0)
> >> > +#define BDMA_DESC_CHECKSUM     (0xff << 8) /* bit8 ~ bit15 */
> >> > +#define BDMA_DESC_BLKPAD       (1 << 17)
> >> > +#define BDMA_DESC_DWPAD                (1 << 18)
> >> > +       u32 next;
> >> > +       u32 ptr;
> >> > +       u32 second_u32;
> >> > +#define BDMA_DESC_BUFLEN       (0xffff) /* bit0 ~ bit15 */
> >> > +};
> >> > +
> >> > +struct msdc_dma {
> >> > +       struct scatterlist *sg; /* I/O scatter list */
> >> > +       struct mt_gpdma_desc *gpd;              /* pointer to gpd
> >> array */
> >> > +       struct mt_bdma_desc *bd;                /* pointer to bd
> >> array */
> >> > +       dma_addr_t gpd_addr;    /* the physical address of gpd array */
> >> > +       dma_addr_t bd_addr;     /* the physical address of bd array */
> >> > +};
> >>
> >> This looks weird from DMA perspective. Can you elaborate on why you
> >> can't use the dmaengine API?
> >>
> > The gpd and bd structure are determined by the MSDC hw, and, the DMA controller is a part of the MSDC hw, different with the chain dma implemented by the kernel.
> 
> Hmm. I haven't reviewed the DMA related parts in detail. I will do
> that when you have sent the next version.
> 
> >> > +
> >> > +struct msdc_host {
> >> > +       struct device *dev;
> >> > +       struct mmc_host *mmc;   /* mmc structure */
> >> > +       int cmd_rsp;
> >> > +
> >> > +       spinlock_t lock;
> >> > +       struct mmc_request *mrq;
> >> > +       struct mmc_command *cmd;
> >> > +       struct mmc_data *data;
> >> > +       int error;
> >> > +
> >> > +       void __iomem *base;             /* host base address */
> >> > +
> >> > +       struct msdc_dma dma;    /* dma channel */
> >> > +
> >> > +       u32 timeout_ns;         /* data timeout ns */
> >> > +       u32 timeout_clks;       /* data timeout clks */
> >> > +
> >> > +       struct pinctrl *pinctrl;
> >> > +       struct pinctrl_state *pins_default;
> >> > +       struct pinctrl_state *pins_uhs;
> >> > +       struct delayed_work req_timeout;
> >> > +       int irq;                /* host interrupt */
> >> > +
> >> > +       struct clk *src_clk;    /* msdc source clock */
> >> > +       u32 mclk;               /* mmc subsystem clock */
> >> > +       u32 hclk;               /* host clock speed */
> >> > +       u32 sclk;               /* SD/MS clock speed */
> >> > +       bool ddr;
> >> > +};
> >> > +
> >> > +static void sdr_set_bits(void __iomem *reg, u32 bs)
> >> > +{
> >> > +       u32 val = readl(reg);
> >> > +
> >> > +       val |= bs;
> >> > +       writel(val, reg);
> >> > +}
> >> > +
> >> > +static void sdr_clr_bits(void __iomem *reg, u32 bs)
> >> > +{
> >> > +       u32 val = readl(reg);
> >> > +
> >> > +       val &= ~(u32)bs;
> >> > +       writel(val, reg);
> >> > +}
> >> > +
> >> > +static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
> >> > +{
> >> > +       unsigned int tv = readl(reg);
> >> > +
> >> > +       tv &= ~field;
> >> > +       tv |= ((val) << (ffs((unsigned int)field) - 1));
> >> > +       writel(tv, reg);
> >> > +}
> >>
> >> A common thought for all the three above functions:
> >>
> >> Have you considered using a cache variable for those registers that
> >> often gets updated? In that way you would have to read the register
> >> value every time when you want to write to it. It should improve
> >> performance a bit.
> >>
> > These register can be modified by the MSDC hw, cannot cache it.
> 
> Is that true for all registers?
> 
> Anyway, let's leave this as is.
> 
> >> > +
> >> > +static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
> >> > +{
> >> > +       unsigned int tv = readl(reg);
> >> > +
> >> > +       *val = ((tv & field) >> (ffs((unsigned int)field) - 1));
> >> > +}
> >> > +
> >> > +static void msdc_reset_hw(struct msdc_host *host)
> >> > +{
> >> > +       u32 val;
> >> > +
> >> > +       sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
> >> > +       while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
> >> > +               cpu_relax();
> >> > +
> >> > +       sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
> >> > +       while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
> >> > +               cpu_relax();
> >> > +
> >> > +       val = readl(host->base + MSDC_INT);
> >> > +       writel(val, host->base + MSDC_INT);
> >> > +}
> >> > +
> >> > +static void msdc_cmd_next(struct msdc_host *host,
> >> > +               struct mmc_request *mrq, struct mmc_command *cmd);
> >>
> >> Please investigate whether you can move around the code to prevent
> >> this static declaration of the function.
> >>
> > It is hard to do it, because the first cmd may be CMD23, and do the next is send the mrq->cmd, so, there is a loop here, at least on method need do static declaration,
> 
> Okay.
> 
> [...]
> 
> >> > +/* clock control primitives */
> >> > +static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
> >> > +{
> >> > +       u32 timeout, clk_ns;
> >> > +       u32 mode = 0;
> >> > +
> >> > +       host->timeout_ns = ns;
> >> > +       host->timeout_clks = clks;
> >> > +       if (host->sclk == 0) {
> >> > +               timeout = 0;
> >> > +       } else {
> >> > +               clk_ns  = 1000000000UL / host->sclk;
> >> > +               timeout = (ns + clk_ns - 1) / clk_ns + clks;
> >> > +               /* in 1048576 sclk cycle unit */
> >> > +               timeout = (timeout + (1 << 20) - 1) >> 20;
> >> > +               sdr_get_field(host->base + MSDC_CFG,
> >> MSDC_CFG_CKMOD, &mode);
> >> > +               /*DDR mode will double the clk cycles for data timeout */
> >>
> >> How do you know you will be using DDR at this point? Don't you need to
> >> check for that?
> >>
> > The MSDC_CFG_CKMODE can show current mode(DDR or SDR).
> 
> Ah, thanks. Got it.
> 
> [...]
> 
> >> > +static void msdc_request_done(struct msdc_host *host, struct
> >> mmc_request *mrq)
> >> > +{
> >> > +       unsigned long flags;
> >> > +
> >> > +       spin_lock_irqsave(&host->lock, flags);
> >> > +       cancel_delayed_work(&host->req_timeout);
> >>
> >> This looks racy.
> >>
> >> Don't you need a cancel_delayed_work_sync() from somewhere, to be sure
> >> that work isn't preemted after the "host->mrq" has been reset here? Or
> >> maybe there is another way!? Of course that can't be done with the
> >> spin_locks held, but I asume you get my point.
> > Yes, I get your point, actually, we set a 5s timeout for each request, and, if the work already pending(means that some error happens), we do not wait it,
> > And the work will set the event to timeout and return,
> > So, maybe a good solution is that need check the return value of the cancel_delayed_work(), if it is pending, directly return, and do not set the host->mrq to 0 to avoid the race condition,
> 
> That should work.
> 
> [...]
> 
> >>
> >> "ocr_avail" should be fetched from the vmmc regulator, when you invoke
> >> mmc_regulator_get_supply() above.
> > Yes, I also want to remove it, but, Not all devices use regulator, our SDIO device which connected on MSDC3, it's power is controlled by gpio.
> > This because the regulator of the PMU is not enough.
> 
> So could you perhaps use a "gpio regulator" for this GPIO pin? There
> is already support to easily describe such in DT.
> 
> Or it is a "reset GPIO" you are talking about?
> 
Will use fixedregulator for sdio case.
Thx!
> [...]
> 
> Kind regards
> Uffe




From s.hauer at pengutronix.de  Sun Apr 12 23:30:18 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 13 Apr 2015 08:30:18 +0200
Subject: [PATCH 13/13] thermal: of: implement .set_trips for device tree
 thermal zones
In-Reply-To: <20150407024307.GH4648@localhost.localdomain>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-14-git-send-email-s.hauer@pengutronix.de>
 <20150407024307.GH4648@localhost.localdomain>
Message-ID: <20150413063018.GT9742@pengutronix.de>

Hi Eduardo,

On Mon, Apr 06, 2015 at 07:43:08PM -0700, Eduardo Valentin wrote:
> On Thu, Mar 26, 2015 at 04:54:00PM +0100, Sascha Hauer wrote:
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> >  drivers/thermal/of-thermal.c | 12 ++++++++++++
> >  include/linux/thermal.h      |  1 +
> >  2 files changed, 13 insertions(+)
> 
> Can you please include at least one user of this call back in your patch
> series?

Thanks for the comments on this series. I'll address them in the next
round. The user for this callback is not yet ready to be posted. I'll
try and move this patch to the end of the series so that the series can
be applied without this one.

Thanks
  Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Mon Apr 13 01:51:42 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 13 Apr 2015 10:51:42 +0200
Subject: [GIT PULL] ARM: mediatek: soc fixes for v4.1
Message-ID: <CABuKBeKGjaySn=X-M-9aG22Kr1y=voA8e7ndjuXBGekmO3Rzvw@mail.gmail.com>

Hi Arnd and Olof,

Please pull the following fix for v4.1.

Thanks,
Matthias

---

The following changes since commit 1f022d84bd193ec88b01c6d2cb5b6647cb20a02f:

  soc: mediatek: Add PMIC wrapper for MT8135 and MT8173 SoCs
(2015-03-30 12:25:40 +0200)

are available in the git repository at:

  https://github.com/mbgg/linux-mediatek.git tags/v4.0-next-soc-fix

for you to fetch changes up to 7a4261d5d35362d1c9ec4f80ba01ad417ca467b7:

  soc/mediatek: Remove unused variables (2015-04-13 10:35:53 +0200)

----------------------------------------------------------------
- fix unused variable warning for pmic-wrapper

----------------------------------------------------------------
Thierry Reding (1):
      soc/mediatek: Remove unused variables

 drivers/soc/mediatek/mtk-pmic-wrap.c | 2 --
 1 file changed, 2 deletions(-)


From s.hauer at pengutronix.de  Mon Apr 13 02:53:06 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 13 Apr 2015 11:53:06 +0200
Subject: [PATCH 4/6] clk: mediatek: Add basic clocks for Mediatek MT8135.
In-Reply-To: <CABuKBeJKrDMR+xHSk_WvppGE7KftMy-QL8ATFi081++C3vaKEg@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <1427825817-26773-5-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJKrDMR+xHSk_WvppGE7KftMy-QL8ATFi081++C3vaKEg@mail.gmail.com>
Message-ID: <20150413095306.GM9742@pengutronix.de>

On Thu, Apr 09, 2015 at 07:05:22PM +0200, Matthias Brugger wrote:
> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> > +
> > +       FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
> > +       FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
> > +       FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
> > +       FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 5),
> 
> shouldn't that be
> FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
> as univpll_249p6m is univpll divided by 5?

Yes, fixed.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 13 02:58:51 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 13 Apr 2015 11:58:51 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
Message-ID: <20150413095851.GN9742@pengutronix.de>

On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
> Hi Sascha,
> 
> 
> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >
> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
> >
> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
> >
> > are available in the git repository at:
> >
> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
> >
> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
> >
> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
> >
> > ----------------------------------------------------------------
> > This patchset contains the initial common clock support for Mediatek SoCs.
> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> > and clock gates.
> 
> I tried the patch set on my mt8135 eval board. I used the dts bindings
> from a former version of this set [1], but it does not boot the board
> (based on v4.0-rc7).
> Do you have any hint, what is happening, or are the bindings wrong?

I can give this a test tomorrow.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 13 03:55:57 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 13 Apr 2015 12:55:57 +0200
Subject: [PATCH 2/4] soc: Mediatek: Add SCPSYS power domain driver
In-Reply-To: <7hbnj9b08m.fsf@deeprootsystems.com>
References: <1426002063-25713-1-git-send-email-s.hauer@pengutronix.de>
 <1426002063-25713-3-git-send-email-s.hauer@pengutronix.de>
 <7hbnj9b08m.fsf@deeprootsystems.com>
Message-ID: <20150413105557.GR9742@pengutronix.de>

On Tue, Mar 31, 2015 at 09:27:53AM -0700, Kevin Hilman wrote:
> Hi Sascha,
> 
> Sascha Hauer <s.hauer at pengutronix.de> writes:
> 
> > This adds a power domain driver for the Mediatek SCPSYS unit.
> >
> > The System Control Processor System (SCPSYS) has several power
> > management related tasks in the system. The tasks include thermal
> > measurement, dynamic voltage frequency scaling (DVFS), interrupt
> > filter and lowlevel sleep control. The System Power Manager (SPM)
> > inside the SCPSYS is for the MTCMOS power domain control.
> >
> > For now this driver only adds power domain support, the more
> > advanced features are not yet supported. The driver implements
> > the generic PM domain device tree bindings, the first user will
> > most likely be the Mediatek AFE audio driver.
> >
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> 
> Sorry for the lag, was travelling last week at ELC and not keeping up
> with reviews.
> 
> This version looks pretty good to me, but had one minor
> comment/question...
> 
> [...]
> 
> > +#define NUM_DOMAINS	ARRAY_SIZE(scp_domain_data)
> > +
> > +struct scp;
> > +
> > +struct scp_domain {
> > +	struct generic_pm_domain pmd;
> > +	struct scp_domain_data *data;
> > +	struct scp *scp;
> > +};
> > +
> > +struct scp {
> > +	struct scp_domain domains[NUM_DOMAINS];
> > +	struct generic_pm_domain *pmd[NUM_DOMAINS];
> 
> Why is this genpd pointer needed?  It's just a pointer to the
> .domains.pmd[i] anyways, and IMO makes the code a bit hard to follow.

The driver itself does not need the genpd pointer, but
of_genpd_add_provider_onecell() expects an array of pointers to struct
generic_pm_domain.

I can allocate the array of pointers separately and remove the pmd field
from struct scp to make this a bit more clearer.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Mon Apr 13 04:36:19 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 13 Apr 2015 13:36:19 +0200
Subject: [PATCH 5/6] clk: mediatek: Add basic clocks for Mediatek MT8173.
In-Reply-To: <1427737245-4064-6-git-send-email-s.hauer@pengutronix.de>
References: <1427737245-4064-1-git-send-email-s.hauer@pengutronix.de>
 <1427737245-4064-6-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeJhm8xTHpnhuhUMxF=dU1iUwf-20OzUQDCpfDjcdx0JZg@mail.gmail.com>

2015-03-30 19:40 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> From: James Liao <jamesjj.liao at mediatek.com>
>
> This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs,
> INFRA and PERI clocks.
>
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/clk/mediatek/Makefile                      |   1 +
>  drivers/clk/mediatek/clk-mt8173.c                  | 826 +++++++++++++++++++++
>  include/dt-bindings/clock/mt8173-clk.h             | 231 ++++++
>  .../dt-bindings/reset-controller/mt8173-resets.h   |  63 ++
>  4 files changed, 1121 insertions(+)
>  create mode 100644 drivers/clk/mediatek/clk-mt8173.c
>  create mode 100644 include/dt-bindings/clock/mt8173-clk.h
>  create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h
>
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> index 12ce576..8e4b2a4 100644
> --- a/drivers/clk/mediatek/Makefile
> +++ b/drivers/clk/mediatek/Makefile
> @@ -1,3 +1,4 @@
>  obj-y += clk-mtk.o clk-pll.o clk-gate.o
>  obj-$(CONFIG_RESET_CONTROLLER) += reset.o
>  obj-y += clk-mt8135.o
> +obj-y += clk-mt8173.o
> diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
> new file mode 100644
> index 0000000..0584554
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt8173.c
> @@ -0,0 +1,826 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +#include <dt-bindings/clock/mt8173-clk.h>
> +
> +static DEFINE_SPINLOCK(mt8173_clk_lock);
> +
> +static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
> +       FACTOR(TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
> +       FACTOR(TOP_DPI_CK, "dpi_ck", "clk_null", 1, 1),
> +       FACTOR(TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
> +       FACTOR(TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
> +};
> +
> +static const struct mtk_fixed_factor top_divs[] __initconst = {
> +       FACTOR(TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
> +       FACTOR(TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
> +
> +       FACTOR(TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
> +       FACTOR(TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
> +       FACTOR(TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
> +       FACTOR(TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
> +
> +       FACTOR(TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
> +       FACTOR(TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
> +
> +       FACTOR(TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
> +       FACTOR(TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
> +       FACTOR(TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
> +       FACTOR(TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
> +       FACTOR(TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
> +
> +       FACTOR(TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
> +       FACTOR(TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
> +       FACTOR(TOP_FPC_CK, "fpc_ck", "clk26m", 1, 1),
> +
> +       FACTOR(TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
> +       FACTOR(TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
> +
> +       FACTOR(TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
> +       FACTOR(TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
> +
> +       FACTOR(TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
> +       FACTOR(TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
> +
> +       FACTOR(TOP_DMPLL_CK, "dmpll_ck", "clkph_mck_o", 1, 1),
> +       FACTOR(TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
> +       FACTOR(TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
> +       FACTOR(TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
> +       FACTOR(TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
> +
> +       FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
> +       FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
> +       FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
> +
> +       FACTOR(TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, 1),
> +       FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
> +
> +       FACTOR(TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
> +       FACTOR(TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
> +       FACTOR(TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
> +       FACTOR(TOP_MSDCPLL2_CK, "msdcpll2_ck", "msdcpll2", 1, 1),
> +       FACTOR(TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
> +       FACTOR(TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
> +
> +       FACTOR(TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
> +       FACTOR(TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
> +       FACTOR(TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
> +       FACTOR(TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
> +       FACTOR(TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
> +       FACTOR(TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
> +       FACTOR(TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
> +       FACTOR(TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
> +       FACTOR(TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
> +       FACTOR(TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
> +       FACTOR(TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
> +       FACTOR(TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
> +       FACTOR(TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
> +       FACTOR(TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
> +
> +       FACTOR(TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll_594m", 1, 1),
> +       FACTOR(TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
> +       FACTOR(TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
> +       FACTOR(TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
> +       FACTOR(TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
> +
> +       FACTOR(TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
> +       FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
> +       FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
> +       FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
> +       FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
> +       FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
> +       FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
> +       FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
> +       FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
> +       FACTOR(TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
> +       FACTOR(TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
> +       FACTOR(TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
> +       FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
> +       FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
> +       FACTOR(TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
> +
> +       FACTOR(TOP_VCODECPLL_CK, "vcodecpll_ck", "vcodecpll", 1, 3),
> +       FACTOR(TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
> +
> +       FACTOR(TOP_VENCPLL_CK, "vencpll_ck", "vencpll", 1, 1),
> +       FACTOR(TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
> +       FACTOR(TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
> +};
> +
> +static const char * const axi_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d2",
> +       "syspll_d5",
> +       "syspll1_d4",
> +       "univpll_d5",
> +       "univpll2_d2",
> +       "dmpll_d2",
> +       "dmpll_d4"
> +};
> +
> +static const char * const mem_parents[] __initconst = {
> +       "clk26m",
> +       "dmpll_ck"
> +};
> +
> +static const char * const ddrphycfg_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d8"
> +};
> +
> +static const char * const mm_parents[] __initconst = {
> +       "clk26m",
> +       "vencpll_d2",
> +       "main_h364m",
> +       "syspll1_d2",
> +       "syspll_d5",
> +       "syspll1_d4",
> +       "univpll1_d2",
> +       "univpll2_d2",
> +       "dmpll_d2"
> +};
> +
> +static const char * const pwm_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d4",
> +       "univpll3_d2",
> +       "univpll1_d4"
> +};
> +
> +static const char * const vdec_parents[] __initconst = {
> +       "clk26m",
> +       "vcodecpll_ck",
> +       "tvdpll_445p5m",
> +       "univpll_d3",
> +       "vencpll_d2",
> +       "syspll_d3",
> +       "univpll1_d2",
> +       "mmpll_d2",
> +       "dmpll_d2",
> +       "dmpll_d4"
> +};
> +
> +static const char * const venc_parents[] __initconst = {
> +       "clk26m",
> +       "vcodecpll_ck",
> +       "tvdpll_445p5m",
> +       "univpll_d3",
> +       "vencpll_d2",
> +       "syspll_d3",
> +       "univpll1_d2",
> +       "univpll2_d2",
> +       "dmpll_d2",
> +       "dmpll_d4"
> +};
> +
> +static const char * const mfg_parents[] __initconst = {
> +       "clk26m",
> +       "mmpll_ck",
> +       "dmpll_ck",
> +       "clk26m",
> +       "clk26m",
> +       "clk26m",
> +       "clk26m",
> +       "clk26m",
> +       "clk26m",
> +       "syspll_d3",
> +       "syspll1_d2",
> +       "syspll_d5",
> +       "univpll_d3",
> +       "univpll1_d2",
> +       "univpll_d5",
> +       "univpll2_d2"
> +};
> +
> +static const char * const camtg_parents[] __initconst = {
> +       "clk26m",
> +       "univpll_d26",
> +       "univpll2_d2",
> +       "syspll3_d2",
> +       "syspll3_d4",
> +       "univpll1_d4"
> +};
> +
> +static const char * const uart_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d8"
> +};
> +
> +static const char * const spi_parents[] __initconst = {
> +       "clk26m",
> +       "syspll3_d2",
> +       "syspll1_d4",
> +       "syspll4_d2",
> +       "univpll3_d2",
> +       "univpll2_d4",
> +       "univpll1_d8"
> +};
> +
> +static const char * const usb20_parents[] __initconst = {
> +       "clk26m",
> +       "univpll1_d8",
> +       "univpll3_d4"
> +};
> +
> +static const char * const usb30_parents[] __initconst = {
> +       "clk26m",
> +       "univpll3_d2",
> +       "usb_syspll_125m",
> +       "univpll2_d4"
> +};
> +
> +static const char * const msdc50_0_h_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d2",
> +       "syspll2_d2",
> +       "syspll4_d2",
> +       "univpll_d5",
> +       "univpll1_d4"
> +};
> +
> +static const char * const msdc50_0_parents[] __initconst = {
> +       "clk26m",
> +       "msdcpll_ck",
> +       "msdcpll_d2",
> +       "univpll1_d4",
> +       "syspll2_d2",
> +       "syspll_d7",
> +       "msdcpll_d4",
> +       "vencpll_d4",
> +       "tvdpll_ck",
> +       "univpll_d2",
> +       "univpll1_d2",
> +       "mmpll_ck",
> +       "msdcpll2_ck",
> +       "msdcpll2_d2",
> +       "msdcpll2_d4"
> +};
> +
> +static const char * const msdc30_1_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d2",
> +       "msdcpll_d4",
> +       "univpll1_d4",
> +       "syspll2_d2",
> +       "syspll_d7",
> +       "univpll_d7",
> +       "vencpll_d4"
> +};
> +
> +static const char * const msdc30_2_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d2",
> +       "msdcpll_d4",
> +       "univpll1_d4",
> +       "syspll2_d2",
> +       "syspll_d7",
> +       "univpll_d7",
> +       "vencpll_d2"
> +};
> +
> +static const char * const msdc30_3_parents[] __initconst = {
> +       "clk26m",
> +       "msdcpll2_ck",
> +       "msdcpll2_d2",
> +       "univpll2_d2",
> +       "msdcpll2_d4",
> +       "msdcpll_d4",
> +       "univpll1_d4",
> +       "syspll2_d2",
> +       "syspll_d7",
> +       "univpll_d7",
> +       "vencpll_d4",
> +       "msdcpll_ck",
> +       "msdcpll_d2",
> +       "msdcpll_d4"
> +};
> +
> +static const char * const audio_parents[] __initconst = {
> +       "clk26m",
> +       "syspll3_d4",
> +       "syspll4_d4",
> +       "syspll1_d16"
> +};
> +
> +static const char * const aud_intbus_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d4",
> +       "syspll4_d2",
> +       "univpll3_d2",
> +       "univpll2_d8",
> +       "dmpll_d4",
> +       "dmpll_d8"
> +};
> +
> +static const char * const pmicspi_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d8",
> +       "syspll3_d4",
> +       "syspll1_d16",
> +       "univpll3_d4",
> +       "univpll_d26",
> +       "dmpll_d8",
> +       "dmpll_d16"
> +};
> +
> +static const char * const scp_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d2",
> +       "univpll_d5",
> +       "syspll_d5",
> +       "dmpll_d2",
> +       "dmpll_d4"
> +};
> +
> +static const char * const atb_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d2",
> +       "univpll_d5",
> +       "dmpll_d2"
> +};
> +
> +static const char * const venc_lt_parents[] __initconst = {
> +       "clk26m",
> +       "univpll_d3",
> +       "vcodecpll_ck",
> +       "tvdpll_445p5m",
> +       "vencpll_d2",
> +       "syspll_d3",
> +       "univpll1_d2",
> +       "univpll2_d2",
> +       "syspll1_d2",
> +       "univpll_d5",
> +       "vcodecpll_370p5",
> +       "dmpll_ck"
> +};
> +
> +static const char * const dpi0_parents[] __initconst = {
> +       "clk26m",
> +       "tvdpll_d2",
> +       "tvdpll_d4",
> +       "clk26m",
> +       "clk26m",
> +       "tvdpll_d8",
> +       "tvdpll_d16"
> +};
> +
> +static const char * const irda_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d4",
> +       "syspll2_d4"
> +};
> +
> +static const char * const cci400_parents[] __initconst = {
> +       "clk26m",
> +       "vencpll_ck",
> +       "armca7pll_754m",
> +       "armca7pll_502m",
> +       "univpll_d2",
> +       "syspll_d2",
> +       "msdcpll_ck",
> +       "dmpll_ck"
> +};
> +
> +static const char * const aud_1_parents[] __initconst = {
> +       "clk26m",
> +       "apll1_ck",
> +       "univpll2_d4",
> +       "univpll2_d8"
> +};
> +
> +static const char * const aud_2_parents[] __initconst = {
> +       "clk26m",
> +       "apll2_ck",
> +       "univpll2_d4",
> +       "univpll2_d8"
> +};
> +
> +static const char * const mem_mfg_in_parents[] __initconst = {
> +       "clk26m",
> +       "mmpll_ck",
> +       "dmpll_ck",
> +       "clk26m"
> +};
> +
> +static const char * const axi_mfg_in_parents[] __initconst = {
> +       "clk26m",
> +       "axi_sel",
> +       "dmpll_d2"
> +};
> +
> +static const char * const scam_parents[] __initconst = {
> +       "clk26m",
> +       "syspll3_d2",
> +       "univpll2_d4",
> +       "dmpll_d4"
> +};
> +
> +static const char * const spinfi_ifr_parents[] __initconst = {
> +       "clk26m",
> +       "univpll2_d8",
> +       "univpll3_d4",
> +       "syspll4_d2",
> +       "univpll2_d4",
> +       "univpll3_d2",
> +       "syspll1_d4",
> +       "univpll1_d4"
> +};
> +
> +static const char * const hdmi_parents[] __initconst = {
> +       "clk26m",
> +       "hdmitx_dig_cts",
> +       "hdmitxpll_d2",
> +       "hdmitxpll_d3"
> +};
> +
> +static const char * const dpilvds_parents[] __initconst = {
> +       "clk26m",
> +       "lvdspll",
> +       "lvdspll_d2",
> +       "lvdspll_d4",
> +       "lvdspll_d8",
> +       "fpc_ck"
> +};
> +
> +static const char * const msdc50_2_h_parents[] __initconst = {
> +       "clk26m",
> +       "syspll1_d2",
> +       "syspll2_d2",
> +       "syspll4_d2",
> +       "univpll_d5",
> +       "univpll1_d4"
> +};
> +
> +static const char * const hdcp_parents[] __initconst = {
> +       "clk26m",
> +       "syspll4_d2",
> +       "syspll3_d4",
> +       "univpll2_d4"
> +};
> +
> +static const char * const hdcp_24m_parents[] __initconst = {
> +       "clk26m",
> +       "univpll_d26",
> +       "univpll_d52",
> +       "univpll2_d8"
> +};
> +
> +static const char * const rtc_parents[] __initconst = {
> +       "clkrtc_int",
> +       "clkrtc_ext",
> +       "clk26m",
> +       "univpll3_d8"
> +};
> +
> +static const char * const i2s0_m_ck_parents[] __initconst = {
> +       "apll1_div1",
> +       "apll2_div1"
> +};
> +
> +static const char * const i2s1_m_ck_parents[] __initconst = {
> +       "apll1_div2",
> +       "apll2_div2"
> +};
> +
> +static const char * const i2s2_m_ck_parents[] __initconst = {
> +       "apll1_div3",
> +       "apll2_div3"
> +};
> +
> +static const char * const i2s3_m_ck_parents[] __initconst = {
> +       "apll1_div4",
> +       "apll2_div4"
> +};
> +
> +static const char * const i2s3_b_ck_parents[] __initconst = {
> +       "apll1_div5",
> +       "apll2_div5"
> +};
> +
> +static const struct mtk_composite top_muxes[] __initconst = {
> +       /* CLK_CFG_0 */
> +       MUX(TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
> +       MUX(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
> +       MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
> +       MUX_GATE(TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
> +       /* CLK_CFG_1 */
> +       MUX_GATE(TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
> +       MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
> +       MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
> +       MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
> +       /* CLK_CFG_2 */
> +       MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
> +       MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
> +       MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
> +       MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
> +       /* CLK_CFG_3 */
> +       MUX_GATE(TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
> +       MUX_GATE(TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
> +       MUX_GATE(TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
> +       MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
> +       /* CLK_CFG_4 */
> +       MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
> +       MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
> +       MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
> +       MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
> +       /* CLK_CFG_5 */
> +       MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
> +       MUX_GATE(TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
> +       MUX_GATE(TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
> +       MUX_GATE(TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
> +       /* CLK_CFG_6 */
> +       MUX_GATE(TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
> +       MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
> +       MUX_GATE(TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
> +       MUX_GATE(TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
> +       /* CLK_CFG_7 */
> +       MUX_GATE(TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
> +       MUX_GATE(TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
> +       MUX_GATE(TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
> +       MUX_GATE(TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
> +       /* CLK_CFG_12 */
> +       MUX_GATE(TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
> +       MUX_GATE(TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
> +       MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
> +       /* CLK_CFG_13 */
> +       MUX_GATE(TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
> +       MUX_GATE(TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
> +       MUX_GATE(TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
> +       MUX(TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
> +
> +       DIV_GATE(TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
> +       DIV_GATE(TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
> +       DIV_GATE(TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
> +       DIV_GATE(TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
> +       DIV_GATE(TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
> +       DIV_GATE(TOP_APLL1_DIV5, "apll1_div5", "aud_1_sel", 0x12c, 13, 0x12c, 4, 0),
> +
> +       DIV_GATE(TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
> +       DIV_GATE(TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
> +       DIV_GATE(TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
> +       DIV_GATE(TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
> +       DIV_GATE(TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
> +       DIV_GATE(TOP_APLL2_DIV5, "apll2_div5", "aud_2_sel", 0x12c, 21, 0x12c, 4, 4),
> +
> +       MUX(TOP_I2S0_M_CK_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
> +       MUX(TOP_I2S1_M_CK_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
> +       MUX(TOP_I2S2_M_CK_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
> +       MUX(TOP_I2S3_M_CK_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
> +       MUX(TOP_I2S3_B_CK_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
> +};
> +
> +static void __init mtk_init_clk_topckgen(void __iomem *top_base,
> +               struct clk_onecell_data *clk_data)
> +{
> +       int i;
> +       struct clk *clk;
> +
> +       for (i = 0; i < ARRAY_SIZE(top_muxes); i++) {
> +               const struct mtk_composite *mux = &top_muxes[i];
> +
> +               clk = mtk_clk_register_composite(mux, top_base, &mt8173_clk_lock);
> +
> +               if (IS_ERR(clk)) {
> +                       pr_err("Failed to register clk %s: %ld\n",
> +                                       mux->name, PTR_ERR(clk));
> +                       continue;
> +               }
> +
> +               if (clk_data)
> +                       clk_data->clks[mux->id] = clk;
> +       }
> +}
> +
> +static const struct mtk_gate_regs infra_cg_regs = {
> +       .set_ofs = 0x0040,
> +       .clr_ofs = 0x0044,
> +       .sta_ofs = 0x0048,
> +};
> +
> +#define GATE_ICG(_id, _name, _parent, _shift) {        \
> +               .id = _id,                                      \
> +               .name = _name,                                  \
> +               .parent_name = _parent,                         \
> +               .regs = &infra_cg_regs,                         \
> +               .shift = _shift,                                \
> +               .ops = &mtk_clk_gate_ops_setclr,                \
> +       }
> +
> +static const struct mtk_gate infra_clks[] __initconst = {
> +       GATE_ICG(INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
> +       GATE_ICG(INFRA_SMI, "infra_smi", "mm_sel", 1),
> +       GATE_ICG(INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
> +       GATE_ICG(INFRA_GCE, "infra_gce", "axi_sel", 6),
> +       GATE_ICG(INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
> +       GATE_ICG(INFRA_M4U, "infra_m4u", "mem_sel", 8),
> +       GATE_ICG(INFRA_CPUM, "infra_cpum", "clk_null", 15),
> +       GATE_ICG(INFRA_KP, "infra_kp", "axi_sel", 16),
> +       GATE_ICG(INFRA_CEC, "infra_cec", "clk26m", 18),
> +       GATE_ICG(INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
> +       GATE_ICG(INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
> +};
> +
> +static const struct mtk_gate_regs peri0_cg_regs = {
> +       .set_ofs = 0x0008,
> +       .clr_ofs = 0x0010,
> +       .sta_ofs = 0x0018,
> +};
> +
> +static const struct mtk_gate_regs peri1_cg_regs = {
> +       .set_ofs = 0x000c,
> +       .clr_ofs = 0x0014,
> +       .sta_ofs = 0x001c,
> +};
> +
> +#define GATE_PERI0(_id, _name, _parent, _shift) {      \
> +               .id = _id,                                      \
> +               .name = _name,                                  \
> +               .parent_name = _parent,                         \
> +               .regs = &peri0_cg_regs,                         \
> +               .shift = _shift,                                \
> +               .ops = &mtk_clk_gate_ops_setclr,                \
> +       }
> +
> +#define GATE_PERI1(_id, _name, _parent, _shift) {      \
> +               .id = _id,                                      \
> +               .name = _name,                                  \
> +               .parent_name = _parent,                         \
> +               .regs = &peri1_cg_regs,                         \
> +               .shift = _shift,                                \
> +               .ops = &mtk_clk_gate_ops_setclr,                \
> +       }
> +
> +static const struct mtk_gate peri_clks[] __initconst = {
> +       /* PERI0 */
> +       GATE_PERI0(PERI_NFI, "peri_nfi", "axi_sel", 0),
> +       GATE_PERI0(PERI_THERM, "peri_therm", "axi_sel", 1),
> +       GATE_PERI0(PERI_PWM1, "peri_pwm1", "axi_sel", 2),
> +       GATE_PERI0(PERI_PWM2, "peri_pwm2", "axi_sel", 3),
> +       GATE_PERI0(PERI_PWM3, "peri_pwm3", "axi_sel", 4),
> +       GATE_PERI0(PERI_PWM4, "peri_pwm4", "axi_sel", 5),
> +       GATE_PERI0(PERI_PWM5, "peri_pwm5", "axi_sel", 6),
> +       GATE_PERI0(PERI_PWM6, "peri_pwm6", "axi_sel", 7),
> +       GATE_PERI0(PERI_PWM7, "peri_pwm7", "axi_sel", 8),
> +       GATE_PERI0(PERI_PWM, "peri_pwm", "axi_sel", 9),
> +       GATE_PERI0(PERI_USB0, "peri_usb0", "usb20_sel", 10),
> +       GATE_PERI0(PERI_USB1, "peri_usb1", "usb20_sel", 11),
> +       GATE_PERI0(PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
> +       GATE_PERI0(PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
> +       GATE_PERI0(PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
> +       GATE_PERI0(PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
> +       GATE_PERI0(PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
> +       GATE_PERI0(PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
> +       GATE_PERI0(PERI_IRDA, "peri_irda", "irda_sel", 18),
> +       GATE_PERI0(PERI_UART0, "peri_uart0", "uart_sel", 19),
> +       GATE_PERI0(PERI_UART1, "peri_uart1", "uart_sel", 20),
> +       GATE_PERI0(PERI_UART2, "peri_uart2", "uart_sel", 21),
> +       GATE_PERI0(PERI_UART3, "peri_uart3", "uart_sel", 22),
> +       GATE_PERI0(PERI_I2C0, "peri_i2c0", "axi_sel", 23),
> +       GATE_PERI0(PERI_I2C1, "peri_i2c1", "axi_sel", 24),
> +       GATE_PERI0(PERI_I2C2, "peri_i2c2", "axi_sel", 25),
> +       GATE_PERI0(PERI_I2C3, "peri_i2c3", "axi_sel", 26),
> +       GATE_PERI0(PERI_I2C4, "peri_i2c4", "axi_sel", 27),
> +       GATE_PERI0(PERI_AUXADC, "peri_auxadc", "clk26m", 28),
> +       GATE_PERI0(PERI_SPI0, "peri_spi0", "spi_sel", 29),
> +       GATE_PERI0(PERI_I2C5, "peri_i2c5", "axi_sel", 30),
> +       GATE_PERI0(PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
> +       /* PERI1 */
> +       GATE_PERI1(PERI_SPI, "peri_spi", "spi_sel", 0),
> +       GATE_PERI1(PERI_IRRX, "peri_irrx", "spi_sel", 1),
> +       GATE_PERI1(PERI_I2C6, "peri_i2c6", "axi_sel", 2),
> +};
> +
> +static void __init mtk_topckgen_init(struct device_node *node)
> +{
> +       struct clk_onecell_data *clk_data;
> +       void __iomem *base;
> +       int r;
> +
> +       base = of_iomap(node, 0);
> +       if (!base) {
> +               pr_err("%s(): ioremap failed\n", __func__);
> +               return;
> +       }
> +
> +       clk_data = mtk_alloc_clk_data(TOP_NR_CLK);
> +
> +       mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
> +       mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
> +       mtk_init_clk_topckgen(base, clk_data);
> +
> +       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +       if (r)
> +               pr_err("%s(): could not register clock provider: %d\n",
> +                       __func__, r);
> +}
> +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
> +
> +static void __init mtk_infrasys_init(struct device_node *node)
> +{
> +       struct clk_onecell_data *clk_data;
> +       int r;
> +
> +       clk_data = mtk_alloc_clk_data(INFRA_NR_CLK);
> +
> +       mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
> +                                               clk_data);
> +
> +       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +       if (r)
> +               pr_err("%s(): could not register clock provider: %d\n",
> +                       __func__, r);
> +
> +       mtk_register_reset_controller(node, 2, 0x30);
> +}
> +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
> +
> +static void __init mtk_pericfg_init(struct device_node *node)
> +{
> +       struct clk_onecell_data *clk_data;
> +       int r;
> +
> +       clk_data = mtk_alloc_clk_data(PERI_NR_CLK);
> +
> +       mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
> +                                               clk_data);
> +
> +       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +       if (r)
> +               pr_err("%s(): could not register clock provider: %d\n",
> +                       __func__, r);
> +
> +       mtk_register_reset_controller(node, 2, 0);
> +}
> +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
> +
> +#define MT8173_PLL_FMAX                (3000UL * MHZ)
> +
> +#define CON0_MT8173_RST_BAR    BIT(24)
> +
> +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
> +                       _tuner_reg, _pcw_reg, _pcw_shift) { \
> +               .id = _id,                                              \
> +               .name = _name,                                          \
> +               .reg = _reg,                                            \
> +               .pwr_reg = _pwr_reg,                                    \
> +               .en_mask = _en_mask,                                    \
> +               .flags = _flags,                                        \
> +               .rst_bar_mask = CON0_MT8173_RST_BAR,                    \
> +               .fmax = MT8173_PLL_FMAX,                                \
> +               .pcwbits = _pcwbits,                                    \
> +               .pd_reg = _pd_reg,                                      \
> +               .pd_shift = _pd_shift,                                  \
> +               .tuner_reg = _tuner_reg,                                \
> +               .pcw_reg = _pcw_reg,                                    \
> +               .pcw_shift = _pcw_shift,                                \
> +       }
> +
> +static const struct mtk_pll_data plls[] = {
> +       PLL(APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
> +       PLL(APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
> +       PLL(APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
> +       PLL(APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
> +       PLL(APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
> +       PLL(APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
> +       PLL(APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
> +       PLL(APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
> +       PLL(APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
> +       PLL(APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
> +       PLL(APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
> +       PLL(APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
> +       PLL(APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
> +       PLL(APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
> +};
> +
> +static void __init mtk_apmixedsys_init(struct device_node *node)
> +{
> +       struct clk_onecell_data *clk_data;
> +
> +       clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
> +       if (!clk_data)
> +               return;
> +
> +       mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
> +}
> +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
> +               mtk_apmixedsys_init);
> diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
> new file mode 100644
> index 0000000..e648b28
> --- /dev/null
> +++ b/include/dt-bindings/clock/mt8173-clk.h
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at mediatek.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.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_MT8173_H
> +#define _DT_BINDINGS_CLK_MT8173_H
> +
> +/* TOPCKGEN */
> +
> +#define TOP_CLKPH_MCK_O                1
> +#define TOP_DPI_CK             2
> +#define TOP_USB_SYSPLL_125M    3
> +#define TOP_HDMITX_DIG_CTS     4
> +#define TOP_ARMCA7PLL_754M     5
> +#define TOP_ARMCA7PLL_502M     6
> +#define TOP_MAIN_H546M         7
> +#define TOP_MAIN_H364M         8
> +#define TOP_MAIN_H218P4M       9
> +#define TOP_MAIN_H156M         10
> +#define TOP_TVDPLL_445P5M      11
> +#define TOP_TVDPLL_594M                12
> +#define TOP_UNIV_624M          13
> +#define TOP_UNIV_416M          14
> +#define TOP_UNIV_249P6M                15
> +#define TOP_UNIV_178P3M                16
> +#define TOP_UNIV_48M           17
> +#define TOP_CLKRTC_EXT         18
> +#define TOP_CLKRTC_INT         19
> +#define TOP_FPC_CK             20
> +#define TOP_HDMITXPLL_D2       21
> +#define TOP_HDMITXPLL_D3       22
> +#define TOP_ARMCA7PLL_D2       23
> +#define TOP_ARMCA7PLL_D3       24
> +#define TOP_APLL1_CK           25
> +#define TOP_APLL2_CK           26
> +#define TOP_DMPLL_CK           27
> +#define TOP_DMPLL_D2           28
> +#define TOP_DMPLL_D4           29
> +#define TOP_DMPLL_D8           30
> +#define TOP_DMPLL_D16          31
> +#define TOP_LVDSPLL_D2         32
> +#define TOP_LVDSPLL_D4         33
> +#define TOP_LVDSPLL_D8         34
> +#define TOP_MMPLL_CK           35
> +#define TOP_MMPLL_D2           36
> +#define TOP_MSDCPLL_CK         37
> +#define TOP_MSDCPLL_D2         38
> +#define TOP_MSDCPLL_D4         39
> +#define TOP_MSDCPLL2_CK                40
> +#define TOP_MSDCPLL2_D2                41
> +#define TOP_MSDCPLL2_D4                42
> +#define TOP_SYSPLL_D2          43
> +#define TOP_SYSPLL1_D2         44
> +#define TOP_SYSPLL1_D4         45
> +#define TOP_SYSPLL1_D8         46
> +#define TOP_SYSPLL1_D16                47
> +#define TOP_SYSPLL_D3          48
> +#define TOP_SYSPLL2_D2         49
> +#define TOP_SYSPLL2_D4         50
> +#define TOP_SYSPLL_D5          51
> +#define TOP_SYSPLL3_D2         52
> +#define TOP_SYSPLL3_D4         53
> +#define TOP_SYSPLL_D7          54
> +#define TOP_SYSPLL4_D2         55
> +#define TOP_SYSPLL4_D4         56
> +#define TOP_TVDPLL_CK          57
> +#define TOP_TVDPLL_D2          58
> +#define TOP_TVDPLL_D4          59
> +#define TOP_TVDPLL_D8          60
> +#define TOP_TVDPLL_D16         61
> +#define TOP_UNIVPLL_D2         62
> +#define TOP_UNIVPLL1_D2                63
> +#define TOP_UNIVPLL1_D4                64
> +#define TOP_UNIVPLL1_D8                65
> +#define TOP_UNIVPLL_D3         66
> +#define TOP_UNIVPLL2_D2                67
> +#define TOP_UNIVPLL2_D4                68
> +#define TOP_UNIVPLL2_D8                69
> +#define TOP_UNIVPLL_D5         70
> +#define TOP_UNIVPLL3_D2                71
> +#define TOP_UNIVPLL3_D4                72
> +#define TOP_UNIVPLL3_D8                73
> +#define TOP_UNIVPLL_D7         74
> +#define TOP_UNIVPLL_D26                75
> +#define TOP_UNIVPLL_D52                76
> +#define TOP_VCODECPLL_CK       77
> +#define TOP_VCODECPLL_370P5    78
> +#define TOP_VENCPLL_CK         79
> +#define TOP_VENCPLL_D2         80
> +#define TOP_VENCPLL_D4         81
> +#define TOP_AXI_SEL            82
> +#define TOP_MEM_SEL            83
> +#define TOP_DDRPHYCFG_SEL      84
> +#define TOP_MM_SEL             85
> +#define TOP_PWM_SEL            86
> +#define TOP_VDEC_SEL           87
> +#define TOP_VENC_SEL           88
> +#define TOP_MFG_SEL            89
> +#define TOP_CAMTG_SEL          90
> +#define TOP_UART_SEL           91
> +#define TOP_SPI_SEL            92
> +#define TOP_USB20_SEL          93
> +#define TOP_USB30_SEL          94
> +#define TOP_MSDC50_0_H_SEL     95
> +#define TOP_MSDC50_0_SEL       96
> +#define TOP_MSDC30_1_SEL       97
> +#define TOP_MSDC30_2_SEL       98
> +#define TOP_MSDC30_3_SEL       99
> +#define TOP_AUDIO_SEL          100
> +#define TOP_AUD_INTBUS_SEL     101
> +#define TOP_PMICSPI_SEL                102
> +#define TOP_SCP_SEL            103
> +#define TOP_ATB_SEL            104
> +#define TOP_VENC_LT_SEL                105
> +#define TOP_DPI0_SEL           106
> +#define TOP_IRDA_SEL           107
> +#define TOP_CCI400_SEL         108
> +#define TOP_AUD_1_SEL          109
> +#define TOP_AUD_2_SEL          110
> +#define TOP_MEM_MFG_IN_SEL     111
> +#define TOP_AXI_MFG_IN_SEL     112
> +#define TOP_SCAM_SEL           113
> +#define TOP_SPINFI_IFR_SEL     114
> +#define TOP_HDMI_SEL           115
> +#define TOP_DPILVDS_SEL                116
> +#define TOP_MSDC50_2_H_SEL     117
> +#define TOP_HDCP_SEL           118
> +#define TOP_HDCP_24M_SEL       119
> +#define TOP_RTC_SEL            120
> +#define TOP_APLL1_DIV0         121
> +#define TOP_APLL1_DIV1         122
> +#define TOP_APLL1_DIV2         123
> +#define TOP_APLL1_DIV3         124
> +#define TOP_APLL1_DIV4         125
> +#define TOP_APLL1_DIV5         126
> +#define TOP_APLL2_DIV0         127
> +#define TOP_APLL2_DIV1         128
> +#define TOP_APLL2_DIV2         129
> +#define TOP_APLL2_DIV3         130
> +#define TOP_APLL2_DIV4         131
> +#define TOP_APLL2_DIV5         132
> +#define TOP_I2S0_M_CK_SEL      133
> +#define TOP_I2S1_M_CK_SEL      134
> +#define TOP_I2S2_M_CK_SEL      135
> +#define TOP_I2S3_M_CK_SEL      136
> +#define TOP_I2S3_B_CK_SEL      137
> +#define TOP_NR_CLK             138
> +
> +/* APMIXED_SYS */
> +
> +#define APMIXED_ARMCA15PLL     1
> +#define APMIXED_ARMCA7PLL      2
> +#define APMIXED_MAINPLL                3
> +#define APMIXED_UNIVPLL                4
> +#define APMIXED_MMPLL          5
> +#define APMIXED_MSDCPLL                6
> +#define APMIXED_VENCPLL                7
> +#define APMIXED_TVDPLL         8
> +#define APMIXED_MPLL           9
> +#define APMIXED_VCODECPLL      10
> +#define APMIXED_APLL1          11
> +#define APMIXED_APLL2          12
> +#define APMIXED_LVDSPLL                13
> +#define APMIXED_MSDCPLL2       14
> +#define APMIXED_NR_CLK         15

APMIXED_NR_CLK is not used. Please delete it. The same applies to mt8135-clk.h

Cheers,
Matthias


From arnd at arndb.de  Mon Apr 13 15:44:16 2015
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 14 Apr 2015 00:44:16 +0200
Subject: [GIT PULL] ARM: mediatek: soc fixes for v4.1
In-Reply-To: <CABuKBeKGjaySn=X-M-9aG22Kr1y=voA8e7ndjuXBGekmO3Rzvw@mail.gmail.com>
References: <CABuKBeKGjaySn=X-M-9aG22Kr1y=voA8e7ndjuXBGekmO3Rzvw@mail.gmail.com>
Message-ID: <201504140044.16204.arnd@arndb.de>

On Monday 13 April 2015, Matthias Brugger wrote:
> Hi Arnd and Olof,
> 
> Please pull the following fix for v4.1.
> 

Thanks a lot for fixing this, merged into next/drivers now.

	Arnd


From yong.wu at mediatek.com  Mon Apr 13 23:31:07 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 14 Apr 2015 14:31:07 +0800
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03>
 <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
Message-ID: <1428993067.13552.14.camel@mhfsdcap03>

Hi Tomasz,

     Thanks very much for you suggestion and explain so detail.
     please help check below.

On Fri, 2015-03-27 at 18:41 +0900, Tomasz Figa wrote:
> Hi Yong Wu,
> 
> Sorry for long delay, I had to figure out some time to look at this again.
> 
> On Wed, Mar 18, 2015 at 8:22 PM, Yong Wu <yong.wu at mediatek.com> wrote:
> >>
> >> > +               imudev = piommu->dev;
> >> > +
> >> > +       spin_lock_irqsave(&priv->portlock, flags);
> >>
> >> What is protected by this spinlock?
> >         We will write a register of the local arbiter while config port. If
> > some modules are in the same local arbiter, it may be overwrite. so I
> > add it here.
> >>
> 
> OK. Maybe it could be called larb_lock then? It would be good to have
> structures or code that should be running under this spinlock
> annotated with proper comments. And purpose of the lock documented in
> a comment as well (probably in a kerneldoc-style documentation of
> priv).
   Thanks. I have move the spinlock into the smi driver, it will lock
for writing the local arbiter regsiter only.
> 
> >> > +static void mtk_iommu_detach_device(struct iommu_domain *domain,
> >> > +                                   struct device *dev)
> >> > +{
> >>
> >> No hardware (de)configuration or clean-up necessary?
> > I will add it. Actually we design like this:If a device have attached to
> > iommu domain, it won't detach from it.
> 
> Isn't proper clean-up required for module removal? Some drivers might
> be required to be loadable modules, which should be unloadable.
> 
> >>
> >> > +
> >> > +       piommu->protect_va = devm_kmalloc(piommu->dev, MTK_PROTECT_PA_ALIGN*2,
> >>
> >> style: Operators like * should have space on both sides.
> >>
> >> > +                                         GFP_KERNEL);
> >>
> >> Shouldn't dma_alloc_coherent() be used for this?
> >      We don't care the data in it. I think they are the same. Could you
> > help tell me why dma_alloc_coherent may be better.
> 
> Can you guarantee that at the time you allocate the memory using
> devm_kmalloc() the memory is not dirty (i.e. some write back data are
> stored in CPU cache) and is not going to be written back in some time,
> overwriting data put there by IOMMU hardware?
> 
As I noted in the function "mtk_iommu_hw_init":

       /* protect memory,HW will write here while translation fault */
       protectpa = __virt_to_phys(piommu->protect_va);

     We don?t care the content of this buffer, It is ok even though its
data is dirty.
    It seem to be a the protect memory. While a translation fault
happened, The iommu HW will overwrite here instead of writing to the
fault physical address which may be 0 or some random address.

> >> > +
> >> > +       iommu_set_fault_handler(domain, mtk_iommu_fault_handler, piommu);
> >>
> >> I don't see any other drivers doing this. Isn't this for upper layers,
> >> so that they can set their own generic fault handlers?
> >      I think that this function is related with the iommu domain, we
> > have only one multimedia iommu domain. so I add it after the iommu
> > domain are created.
> 
> No, this function is for drivers of IOMMU clients (i.e. master IP
> blocks) which want to subscribe to page fault to do things like paging
> on demand and so on. It shouldn't be called by IOMMU driver. Please
> see other IOMMU drivers, for example rockchip-iommmu.c.
     Thanks. I have read it. I will delete it and print the error info
in the ISR. Also call the report_iommu_fault in the ISR.

> Best regards,
> Tomasz




From yong.wu at mediatek.com  Mon Apr 13 23:50:09 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 14 Apr 2015 14:50:09 +0800
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <550C71B3.1080708@arm.com>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03> <550C71B3.1080708@arm.com>
Message-ID: <1428994209.13552.29.camel@mhfsdcap03>

Hi Robin,
      Thanks very much for your confirm.
      About the v3 of the DMA-mapping, I have some question below.

On Fri, 2015-03-20 at 19:14 +0000, Robin Murphy wrote:
> On 18/03/15 11:22, Yong Wu wrote:
> > Hi Tomasz,
> >     Thanks very much for your review. please help check below.
> > The others I will fix in the next version.
> >
> > Hi Robin,
> >     There are some place I would like you can have a look and give me
> > some suggestion.
> >
> > On Wed, 2015-03-11 at 19:53 +0900, Tomasz Figa wrote:
> >> Hi,
> >>
> >> Please find next part of my comments inline.
> >>
> >>> +/*
> >>> + * pimudev is a global var for dma_alloc_coherent.
> >>> + * It is not accepatable, we will delete it if "domain_alloc" is enabled
> >>
> >> It looks like we indeed need to use dma_alloc_coherent() and we don't
> >> have a good way to pass the device pointer to domain_init callback.
> >>
> >> If you don't expect SoCs in the nearest future to have multiple M4U
> >> blocks, then I guess this global variable could stay, after changing
> >> the comment into an explanation why it's correct. Also it should be
> >> moved to the top of the file, below #include directives, as this is
> >> where usually global variables are located.
> > @Robin,
> >       We have merged this patch[0] in order to delete the global var, But
> > it seems that your patch of "arm64:IOMMU" isn't based on it right row.
> > it will build fail.
> 
> Yeah, I've not yet managed to try pulling in that series (much as I 
> approve of it), partly as I know doing so is going to lean towards a 
> not-insignificant rework and I'd rather avoid picking up more unmerged 
> dependencies to block getting _something_ in for arm64 (which we can 
> then improve).
> 
> >
> > [0]:http://lists.linuxfoundation.org/pipermail/iommu/2015-January/011939.html
> >
[snip]
> 
> Calling arch_setup_dma_ops() from the driver looks plain wrong, 
> especially given that you apparently attach the IOMMU to itself - if you 
> want your own domain you should use iommu_dma_create_domain(). I admit 
> that still leaves you having to dance around a bit in order to tear down 
> the automatic domains for now, but hopefully we'll get the core code 
> sorted out sooner rather than later.
> >>> +
> >>> +                       mtk_iommu_config_port(piommu, portid);
> >>> +
> >>> +                       if (i == 0)
> >>> +                               dev->archdata.dma_ops =
> >>> +                                       piommu->dev->archdata.dma_ops;
> >>
> >> Shouldn't this be set automatically by IOMMU or DMA mapping core?
> > @Robin,
> >       In the original "arm_iommu_attach_device" of arm/mm, it will call
> > set_dma_ops to add iommu_ops for each iommu device.
> > But iommu_dma_attach_device don't help this, so I have to add it here.
> > Could this be improved?
> 
> If you implemented a simple of_xlate callback so that the core code 
> handles the dma_ops as intended, I think the simplest cheat would be to 
> check the client device's domain, either on attachment or when they 
> start mapping/unmapping, and move them to your own domain if necessary. 
> I'm putting together a v3 of the DMA mapping series, so I'll have a look 
> to see if I can squeeze in a way to make that a bit less painful until 
> we solve it properly.
> 
> 
> Robin.
> 
      I have implemented a simple of_xlate, but I can?t get the standard
struct dma_map_ops ?iommu_dma_ops? to assigned it to the client device.
So the v3 of dma mapping will improve this issue?  

      And Is the v3 of the DMA-mapping based on 4.0-rc1? because we
expect it could contain will?s io-pagetable.

      And when the v3 will be ready?
> >>
> >>> +               }
> >>> +               i++;
> >>> +       }
> >>> +
> >>> +       spin_unlock_irqrestore(&priv->portlock, flags);
> >>> +
> >>> +imudev:
> >>> +       return 0;
> >>> +}
> >>> +
> >>> +static void mtk_iommu_detach_device(struct iommu_domain *domain,
> >>> +                                   struct device *dev)
> >>> +{
> >>
> >> No hardware (de)configuration or clean-up necessary?
> > I will add it. Actually we design like this:If a device have attached to
> > iommu domain, it won't detach from it.
> >>
> >>> +}
> >>> +
> > [snip]




From yong.wu at mediatek.com  Tue Apr 14 02:07:54 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 14 Apr 2015 17:07:54 +0800
Subject: [PATCH 3/5] dt-bindings: mediatek: Add smi dts binding
In-Reply-To: <20150306111338.GD8700@leverpostej>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-4-git-send-email-yong.wu@mediatek.com>
 <20150306111338.GD8700@leverpostej>
Message-ID: <1429002474.14855.7.camel@mhfsdcap03>

Hi Mark,
    Thanks very much for review. 
    About the clock name should be the PoV of _this_ device. Could you
help check below?

On Fri, 2015-03-06 at 11:13 +0000, Mark Rutland wrote:
> On Fri, Mar 06, 2015 at 10:48:18AM +0000, yong.wu at mediatek.com wrote:
> > From: Yong Wu <yong.wu at mediatek.com>
> > 
> > This patch add smi binding document.
> 
> Please move binding documents to the start of the series. It makes
> things far easier to review.
> 
> > 
> > Signed-off-by: Yong Wu <yong.wu at mediatek.com>
> > +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,smi.txt
> > @@ -0,0 +1,17 @@
> > +SMI hardware block diagram please help check <bindings/iommu/mediatek,iommu.txt>
> > +
> > +Required properties:
> > +- compatible : must be "mediatek,mediatek,mt8173-smi-larb"
> 
> Double vendor prefix?
> 
> What does "larb" mean? It would be nice for the intorductory paragraph
> in this file to explain.
> 
> > +- reg : the register of each local arbiter
> > +- clocks : the clocks of each local arbiter
> > +- clock-name: larb_sub*(3 clockes at most)
> 
> The names required _must_ be specified here, or clock-names is
> pointless.
> 
> The clock names should be from the PoV of _this_ device (i.e. they
> should be the names of the inputs) not from the PoV of the provider
> (i.e. they should not be the names of the outputs from the provider).
> 
> Mark.
> 
     After we check with our SMI Designer. Every SMI local arbiter need
two clocks, which is called  APB clocks and SMI clock.
     APB clock : Advanced Peripheral Bus Clock. It is the clock for
setting the register of local arbiter.
     SMI clock : Smart Multimedia Interface Clock, It is the clock for
transfering the data and command. 

     And all the local arbiters need the smi common clock, so we
separate it. 

     Then I prepare to design the smi the dtsi like this: 

      smi_common:smi at 14022000 {
                 compatible = ?mediate, mt8173-smi?;
                 reg = <0 0x14022000 0 0x1000>;
                 clocks = <&mmsys MM_SMI_COMMON>;
                 clocks-names = ?smi_common?;
      };

      larb0: larb at 14021000 {
                 compatible = ?mediate, mt8173-smi-larb?;
                 reg = <0 0x14021000 0 0x1000>;
                 smi = <&smi_common>;
                 clocks = <&mmsys MM_SMI_LARB0>, 
		 	<&mmsys MM_SMI_LARB0>;
                 clocks-names = ?apb_clk?, ?smi_clk?;
     };

     larb1: larb at 16010000 {
                 compatible = ?mediate, mt8173-smi-larb?;
                 reg = <0 0x16010000 0 0x1000>;
                 smi = <&smi_common>;
                 clocks = <&vdecsys VDEC_CKEN>, 
			 <&mmsys VDEC_LARB_CKEN>;
                 clocks-names = ?apb_clk?, ?smi_clk?;
      };
      ? 
     In some local arbiter, the source clock of the APB clock and the
SMI clock may be the same, like larb0. so the two clocks are the same.
And they may be different in other local arbiteres, like larb1.      

     If it is designed like this, is it ok?

> > +
> > +Example:
> > +	larb1:larb at 16010000 {
> > +	        compatible = "mediatek,mt8173-smi-larb";
> > +		reg = <0 0x16010000 0 0x1000>;
> > +		clocks = <&mmsys MM_SMI_COMMON>,
> > +		        <&vdecsys VDEC_CKEN>,
> > +                        <&vdecsys VDEC_LARB_CKEN>;
> > +		clock-names = "larb_sub0", "larb_sub1", "larb_sub2";
> > +	};
> > -- 
> > 1.8.1.1.dirty
> > 
> > 




From mark.rutland at arm.com  Tue Apr 14 03:06:58 2015
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 14 Apr 2015 11:06:58 +0100
Subject: [PATCH 3/5] dt-bindings: mediatek: Add smi dts binding
In-Reply-To: <1429002474.14855.7.camel@mhfsdcap03>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-4-git-send-email-yong.wu@mediatek.com>
 <20150306111338.GD8700@leverpostej>
 <1429002474.14855.7.camel@mhfsdcap03>
Message-ID: <20150414100657.GB28709@leverpostej>

On Tue, Apr 14, 2015 at 10:07:54AM +0100, Yong Wu wrote:
> Hi Mark,
>     Thanks very much for review. 
>     About the clock name should be the PoV of _this_ device. Could you
> help check below?
> 
> On Fri, 2015-03-06 at 11:13 +0000, Mark Rutland wrote:
> > On Fri, Mar 06, 2015 at 10:48:18AM +0000, yong.wu at mediatek.com wrote:
> > > From: Yong Wu <yong.wu at mediatek.com>
> > > 
> > > This patch add smi binding document.
> > 
> > Please move binding documents to the start of the series. It makes
> > things far easier to review.
> > 
> > > 
> > > Signed-off-by: Yong Wu <yong.wu at mediatek.com>
> > > +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,smi.txt
> > > @@ -0,0 +1,17 @@
> > > +SMI hardware block diagram please help check <bindings/iommu/mediatek,iommu.txt>
> > > +
> > > +Required properties:
> > > +- compatible : must be "mediatek,mediatek,mt8173-smi-larb"
> > 
> > Double vendor prefix?
> > 
> > What does "larb" mean? It would be nice for the intorductory paragraph
> > in this file to explain.
> > 
> > > +- reg : the register of each local arbiter
> > > +- clocks : the clocks of each local arbiter
> > > +- clock-name: larb_sub*(3 clockes at most)
> > 
> > The names required _must_ be specified here, or clock-names is
> > pointless.
> > 
> > The clock names should be from the PoV of _this_ device (i.e. they
> > should be the names of the inputs) not from the PoV of the provider
> > (i.e. they should not be the names of the outputs from the provider).
> > 
> > Mark.
> > 
>      After we check with our SMI Designer. Every SMI local arbiter need
> two clocks, which is called  APB clocks and SMI clock.
>      APB clock : Advanced Peripheral Bus Clock. It is the clock for
> setting the register of local arbiter.
>      SMI clock : Smart Multimedia Interface Clock, It is the clock for
> transfering the data and command. 
> 
>      And all the local arbiters need the smi common clock, so we
> separate it. 
> 
>      Then I prepare to design the smi the dtsi like this: 
> 
>       smi_common:smi at 14022000 {
>                  compatible = ?mediate, mt8173-smi?;
>                  reg = <0 0x14022000 0 0x1000>;
>                  clocks = <&mmsys MM_SMI_COMMON>;
>                  clocks-names = ?smi_common?;
>       };
> 
>       larb0: larb at 14021000 {
>                  compatible = ?mediate, mt8173-smi-larb?;
>                  reg = <0 0x14021000 0 0x1000>;
>                  smi = <&smi_common>;
>                  clocks = <&mmsys MM_SMI_LARB0>, 
> 		 	<&mmsys MM_SMI_LARB0>;
>                  clocks-names = ?apb_clk?, ?smi_clk?;
>      };
> 
>      larb1: larb at 16010000 {
>                  compatible = ?mediate, mt8173-smi-larb?;
>                  reg = <0 0x16010000 0 0x1000>;
>                  smi = <&smi_common>;
>                  clocks = <&vdecsys VDEC_CKEN>, 
> 			 <&mmsys VDEC_LARB_CKEN>;
>                  clocks-names = ?apb_clk?, ?smi_clk?;
>       };
>       ? 
>      In some local arbiter, the source clock of the APB clock and the
> SMI clock may be the same, like larb0. so the two clocks are the same.
> And they may be different in other local arbiteres, like larb1.      
> 
>      If it is designed like this, is it ok?

That looks pretty good; the clocks and names on the larb nodes seem
sensible.

The naming of the "smi_common" clock on the smi_common node looks a bit
odd though. Is that really what the clock input is called?

Mark.


From s.hauer at pengutronix.de  Tue Apr 14 03:08:10 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 14 Apr 2015 12:08:10 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
Message-ID: <20150414100810.GH4946@pengutronix.de>

Hi Matthias,

On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
> Hi Sascha,
> 
> 
> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >
> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
> >
> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
> >
> > are available in the git repository at:
> >
> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
> >
> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
> >
> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
> >
> > ----------------------------------------------------------------
> > This patchset contains the initial common clock support for Mediatek SoCs.
> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> > and clock gates.
> 
> I tried the patch set on my mt8135 eval board. I used the dts bindings
> from a former version of this set [1], but it does not boot the board
> (based on v4.0-rc7).
> Do you have any hint, what is happening, or are the bindings wrong?

I just tried on a v4.0 with
- this series applied
- the dts patch applied (which is still up-to-date)
- multi_v7_defconfig

And it still works. What do you mean with "does not boot the board"? No
console output? Could you try with earlyprintk?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 14 03:44:47 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 14 Apr 2015 12:44:47 +0200
Subject: [PATCH 05/13] thermal: inline only once used function
In-Reply-To: <20150407022307.GE4648@localhost.localdomain>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-6-git-send-email-s.hauer@pengutronix.de>
 <20150407022307.GE4648@localhost.localdomain>
Message-ID: <20150414104447.GI4946@pengutronix.de>

On Mon, Apr 06, 2015 at 07:23:08PM -0700, Eduardo Valentin wrote:
> On Thu, Mar 26, 2015 at 04:53:52PM +0100, Sascha Hauer wrote:
> > Inline update_temperature into its only caller to make the code
> > more readable.
> 
> I am not sure I understand how this is improving readability, can you
> please elaborate?

It improves readability because the reader does not have to lookup the
definition of update_temperature but can instead just read through. The
function name "update_temperature" does not give new information either,
so I thought inlining the code is a good idea. Anyway, I can skip this
patch if you want.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 14 03:48:36 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 14 Apr 2015 12:48:36 +0200
Subject: [PATCH 06/13] thermal: streamline get_trend callbacks
In-Reply-To: <20150407031950.GK4648@localhost.localdomain>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-7-git-send-email-s.hauer@pengutronix.de>
 <20150407031950.GK4648@localhost.localdomain>
Message-ID: <20150414104836.GJ4946@pengutronix.de>

On Mon, Apr 06, 2015 at 08:19:52PM -0700, Eduardo Valentin wrote:
> On Thu, Mar 26, 2015 at 04:53:53PM +0100, Sascha Hauer wrote:
> > The .get_trend callback in struct thermal_zone_device_ops has the prototype:
> > 
> > 	int (*get_trend) (struct thermal_zone_device *, int,
> > 			  enum thermal_trend *);
> > 
> > whereas the .get_trend callback in struct thermal_zone_of_device_ops has:
> > 
> > 	int (*get_trend)(void *, long *);
> > 
> > Streamline both prototypes and add the trip argument to the OF callback
> > aswell and use enum thermal_trend * instead of an integer pointer.
> > 
> > While the OF prototype may be the better one, this should be decided at
> > framework level and not on OF level.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> >  drivers/thermal/of-thermal.c                       | 11 +---------
> >  drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++++---------------
> >  include/linux/thermal.h                            |  2 +-
> >  3 files changed, 10 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> > index 668fb1b..b39e22f 100644
> > --- a/drivers/thermal/of-thermal.c
> > +++ b/drivers/thermal/of-thermal.c
> > @@ -187,24 +187,15 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
> >  				enum thermal_trend *trend)
> >  {
> >  	struct __thermal_zone *data = tz->devdata;
> > -	long dev_trend;
> >  	int r;
> >  
> >  	if (!data->ops->get_trend)
> >  		return -EINVAL;
> >  
> > -	r = data->ops->get_trend(data->sensor_data, &dev_trend);
> > +	r = data->ops->get_trend(data->sensor_data, trip, trend);
> >  	if (r)
> >  		return r;
> >  
> > -	/* TODO: These intervals might have some thresholds, but in core code */
> > -	if (dev_trend > 0)
> > -		*trend = THERMAL_TREND_RAISING;
> > -	else if (dev_trend < 0)
> > -		*trend = THERMAL_TREND_DROPPING;
> > -	else
> > -		*trend = THERMAL_TREND_STABLE;
> > -
> >  	return 0;
> >  }
> >  
> > diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> > index a38c175..7f8e5f3 100644
> > --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> > +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
> > @@ -238,7 +238,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
> >  	return 0;
> >  }
> >  
> > -static int __ti_thermal_get_trend(void *p, long *trend)
> > +static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
> >  {
> >  	struct ti_thermal_data *data = p;
> >  	struct ti_bandgap *bgp;
> > @@ -251,22 +251,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
> >  	if (ret)
> >  		return ret;
> >  
> > -	*trend = tr;
> > -
> > -	return 0;
> > -}
> > -
> > -/* Get the temperature trend callback functions for thermal zone */
> > -static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
> > -				int trip, enum thermal_trend *trend)
> > -{
> > -	int ret;
> > -	long tr;
> > -
> > -	ret = __ti_thermal_get_trend(thermal->devdata, &tr);
> > -	if (ret)
> > -		return ret;
> > -
> >  	if (tr > 0)
> >  		*trend = THERMAL_TREND_RAISING;
> >  	else if (tr < 0)
> > @@ -277,6 +261,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
> >  	return 0;
> >  }
> >  
> > +/* Get the temperature trend callback functions for thermal zone */
> > +static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
> > +				int trip, enum thermal_trend *trend)
> > +{
> > +	return __ti_thermal_get_trend(thermal->devdata, trip, trend);
> > +}
> > +
> >  /* Get critical temperature callback functions for thermal zone */
> >  static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
> >  				    unsigned long *temp)
> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> > index db6c12b..ba2e29a 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -273,7 +273,7 @@ struct thermal_genl_event {
> >   */
> >  struct thermal_zone_of_device_ops {
> >  	int (*get_temp)(void *, long *);
> > -	int (*get_trend)(void *, long *);
> > +	int (*get_trend)(void *, int trend, enum thermal_trend *);
> 
> Could you please keep the kernel doc entry up to date?

What do you mean? The kernel doc entry for this function contains:

 * @get_trend: a pointer to a function that reads the sensor temperature trend.

This is still valid with my patch, so I might not understand what I
should keep up to date.

That said, the argument name above should be 'int trip', not 'int
trend'. I'll change that.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 14 03:54:19 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 14 Apr 2015 12:54:19 +0200
Subject: [PATCH 09/13] thermal: of: always set sensor related callbacks
In-Reply-To: <20150407032522.GL4648@localhost.localdomain>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-10-git-send-email-s.hauer@pengutronix.de>
 <20150407032522.GL4648@localhost.localdomain>
Message-ID: <20150414105419.GK4946@pengutronix.de>

On Mon, Apr 06, 2015 at 08:25:23PM -0700, Eduardo Valentin wrote:
> On Thu, Mar 26, 2015 at 04:53:56PM +0100, Sascha Hauer wrote:
> > Now that the thermal core treats -ENOSYS like the callbacks were
> > not present at all we no longer have to overwrite the ops during
> > runtime but instead can always set them and return -ENOSYS if no
> > sensor is registered.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> >  drivers/thermal/of-thermal.c | 18 +++++++++++-------
> >  1 file changed, 11 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
> > index b39e22f..df14fdd 100644
> > --- a/drivers/thermal/of-thermal.c
> > +++ b/drivers/thermal/of-thermal.c
> > @@ -91,7 +91,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
> >  {
> >  	struct __thermal_zone *data = tz->devdata;
> >  
> > -	if (!data->ops->get_temp)
> > +	if (!data->ops)
> >  		return -EINVAL;
> >  
> >  	return data->ops->get_temp(data->sensor_data, temp);
> > @@ -178,7 +178,7 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
> >  	struct __thermal_zone *data = tz->devdata;
> >  
> >  	if (!data->ops || !data->ops->set_emul_temp)
> > -		return -EINVAL;
> > +		return -ENOSYS;
> >  
> >  	return data->ops->set_emul_temp(data->sensor_data, temp);
> >  }
> > @@ -189,8 +189,8 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
> >  	struct __thermal_zone *data = tz->devdata;
> >  	int r;
> >  
> > -	if (!data->ops->get_trend)
> > -		return -EINVAL;
> > +	if (!data->ops || !data->ops->get_trend)
> > +		return -ENOSYS;
> >  
> >  	r = data->ops->get_trend(data->sensor_data, trip, trend);
> >  	if (r)
> > @@ -366,6 +366,10 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
> >  }
> >  
> >  static struct thermal_zone_device_ops of_thermal_ops = {
> > +	.get_temp = of_thermal_get_temp,
> > +	.get_trend = of_thermal_get_trend,
> > +	.set_emul_temp = of_thermal_set_emul_temp,
> > +
> >  	.get_mode = of_thermal_get_mode,
> >  	.set_mode = of_thermal_set_mode,
> >  
> > @@ -399,13 +403,13 @@ thermal_zone_of_add_sensor(struct device_node *zone,
> >  	if (!ops)
> >  		return ERR_PTR(-EINVAL);
> >  
> > +	if (!ops->get_temp)
> > +		return ERR_PTR(-EINVAL);
> > +
> >  	mutex_lock(&tzd->lock);
> >  	tz->ops = ops;
> >  	tz->sensor_data = data;
> >  
> > -	tzd->ops->get_temp = of_thermal_get_temp;
> > -	tzd->ops->get_trend = of_thermal_get_trend;
> > -	tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
> 
> You may want to update the thermal_zone_of_sensor_unregister too.

Ups, indeed. That hunk accidently went into a later patch.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Tue Apr 14 04:01:30 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 14 Apr 2015 13:01:30 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <20150414100810.GH4946@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
Message-ID: <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>

Hi Sascha,

2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> Hi Matthias,
>
> On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
>> Hi Sascha,
>>
>>
>> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> >
>> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
>> >
>> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
>> >
>> > are available in the git repository at:
>> >
>> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
>> >
>> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
>> >
>> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
>> >
>> > ----------------------------------------------------------------
>> > This patchset contains the initial common clock support for Mediatek SoCs.
>> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
>> > and clock gates.
>>
>> I tried the patch set on my mt8135 eval board. I used the dts bindings
>> from a former version of this set [1], but it does not boot the board
>> (based on v4.0-rc7).
>> Do you have any hint, what is happening, or are the bindings wrong?
>
> I just tried on a v4.0 with
> - this series applied
> - the dts patch applied (which is still up-to-date)
> - multi_v7_defconfig
>
> And it still works. What do you mean with "does not boot the board"? No
> console output? Could you try with earlyprintk?

The probelms I see is, that with the clock patches, I'm not able to
boot into a initramfs [1].
Whereas if I just comment topckgen and preicfg in the dts, I'm able to
get the a serial console of my initramfs [2].

I wonder if you are able to get serial console from the initramfs with
the clock patches + dts patch?

Cheers,
Matthias

[1] http://pastebin.com/wmmsbdNp
[2] http://pastebin.com/jZHrxmmT


From s.hauer at pengutronix.de  Tue Apr 14 04:57:02 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 14 Apr 2015 13:57:02 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
 <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
Message-ID: <20150414115702.GX9742@pengutronix.de>

On Tue, Apr 14, 2015 at 01:01:30PM +0200, Matthias Brugger wrote:
> Hi Sascha,
> 
> 2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> > Hi Matthias,
> >
> > On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
> >> Hi Sascha,
> >>
> >>
> >> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >> >
> >> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
> >> >
> >> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
> >> >
> >> > are available in the git repository at:
> >> >
> >> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
> >> >
> >> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
> >> >
> >> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
> >> >
> >> > ----------------------------------------------------------------
> >> > This patchset contains the initial common clock support for Mediatek SoCs.
> >> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> >> > and clock gates.
> >>
> >> I tried the patch set on my mt8135 eval board. I used the dts bindings
> >> from a former version of this set [1], but it does not boot the board
> >> (based on v4.0-rc7).
> >> Do you have any hint, what is happening, or are the bindings wrong?
> >
> > I just tried on a v4.0 with
> > - this series applied
> > - the dts patch applied (which is still up-to-date)
> > - multi_v7_defconfig
> >
> > And it still works. What do you mean with "does not boot the board"? No
> > console output? Could you try with earlyprintk?
> 
> The probelms I see is, that with the clock patches, I'm not able to
> boot into a initramfs [1].
> Whereas if I just comment topckgen and preicfg in the dts, I'm able to
> get the a serial console of my initramfs [2].
> 
> I wonder if you are able to get serial console from the initramfs with
> the clock patches + dts patch?

So you get kernel messages but no output from initramfs? In this case
the kernel disables the unused clocks in a late_initcall. The UART
driver still uses the dummy clock provided in the dtsi, so the real
UART clk gets disabled in the initcall. Try passing clk_ignore_unused to
the kernel

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From yong.wu at mediatek.com  Tue Apr 14 06:49:49 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 14 Apr 2015 21:49:49 +0800
Subject: [PATCH 3/5] dt-bindings: mediatek: Add smi dts binding
In-Reply-To: <20150414100657.GB28709@leverpostej>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-4-git-send-email-yong.wu@mediatek.com>
 <20150306111338.GD8700@leverpostej> <1429002474.14855.7.camel@mhfsdcap03>
 <20150414100657.GB28709@leverpostej>
Message-ID: <1429019389.16264.5.camel@mhfsdcap03>

Hi Mark,

On Tue, 2015-04-14 at 11:06 +0100, Mark Rutland wrote:
> On Tue, Apr 14, 2015 at 10:07:54AM +0100, Yong Wu wrote:
> > Hi Mark,
> >     Thanks very much for review. 
> >     About the clock name should be the PoV of _this_ device. Could you
> > help check below?
> > 
> > On Fri, 2015-03-06 at 11:13 +0000, Mark Rutland wrote:
> > > On Fri, Mar 06, 2015 at 10:48:18AM +0000, yong.wu at mediatek.com wrote:
> > > > From: Yong Wu <yong.wu at mediatek.com>
> > > > 
> > > > This patch add smi binding document.
> > > 
> > > Please move binding documents to the start of the series. It makes
> > > things far easier to review.
> > >  
> > > What does "larb" mean? It would be nice for the intorductory paragraph
> > > in this file to explain.
> > > 
> > > > +- reg : the register of each local arbiter
> > > > +- clocks : the clocks of each local arbiter
> > > > +- clock-name: larb_sub*(3 clockes at most)
> > > 
> > > The names required _must_ be specified here, or clock-names is
> > > pointless.
> > > 
> > > The clock names should be from the PoV of _this_ device (i.e. they
> > > should be the names of the inputs) not from the PoV of the provider
> > > (i.e. they should not be the names of the outputs from the provider).
> > > 
> > > Mark.
> > > 
> >      After we check with our SMI Designer. Every SMI local arbiter need
> > two clocks, which is called  APB clocks and SMI clock.
> >      APB clock : Advanced Peripheral Bus Clock. It is the clock for
> > setting the register of local arbiter.
> >      SMI clock : Smart Multimedia Interface Clock, It is the clock for
> > transfering the data and command. 
> > 
> >      And all the local arbiters need the smi common clock, so we
> > separate it. 
> > 
> >      Then I prepare to design the smi the dtsi like this: 
> > 
> >       smi_common:smi at 14022000 {
> >                  compatible = ?mediate, mt8173-smi?;
> >                  reg = <0 0x14022000 0 0x1000>;
> >                  clocks = <&mmsys MM_SMI_COMMON>;
> >                  clocks-names = ?smi_common?;
> >       };
> > 
> >       larb0: larb at 14021000 {
> >                  compatible = ?mediate, mt8173-smi-larb?;
> >                  reg = <0 0x14021000 0 0x1000>;
> >                  smi = <&smi_common>;
> >                  clocks = <&mmsys MM_SMI_LARB0>, 
> > 		 	<&mmsys MM_SMI_LARB0>;
> >                  clocks-names = ?apb_clk?, ?smi_clk?;
> >      };
> > 
> >      larb1: larb at 16010000 {
> >                  compatible = ?mediate, mt8173-smi-larb?;
> >                  reg = <0 0x16010000 0 0x1000>;
> >                  smi = <&smi_common>;
> >                  clocks = <&vdecsys VDEC_CKEN>, 
> > 			 <&mmsys VDEC_LARB_CKEN>;
> >                  clocks-names = ?apb_clk?, ?smi_clk?;
> >       };
> >       ? 
> >      In some local arbiter, the source clock of the APB clock and the
> > SMI clock may be the same, like larb0. so the two clocks are the same.
> > And they may be different in other local arbiteres, like larb1.      
> > 
> >      If it is designed like this, is it ok?
> 
> That looks pretty good; the clocks and names on the larb nodes seem
> sensible.
> 
> The naming of the "smi_common" clock on the smi_common node looks a bit
> odd though. Is that really what the clock input is called?
> 
> Mark.
     After check with DE, the smi_common clock also have its APB clock
and the smi clock(they have the same clock source).
    And I prepare to delete "_clk" in all the clock-names.
    So it may be like this:
         smi_common:smi at 14022000 {
                 compatible = ?mediate, mt8173-smi?;
                    reg = <0 0x14022000 0 0x1000>;
                  clocks = <&mmsys MM_SMI_COMMON>, 
			   <&mmsys MM_SMI_COMMON>;
                  clocks-names = ?apk?,"smi";
        };
     How about this?
   






From yong.wu at mediatek.com  Tue Apr 14 06:55:42 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 14 Apr 2015 21:55:42 +0800
Subject: [PATCH 3/5] dt-bindings: mediatek: Add smi dts binding
In-Reply-To: <1429019389.16264.5.camel@mhfsdcap03>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-4-git-send-email-yong.wu@mediatek.com>
 <20150306111338.GD8700@leverpostej> <1429002474.14855.7.camel@mhfsdcap03>
 <20150414100657.GB28709@leverpostej> <1429019389.16264.5.camel@mhfsdcap03>
Message-ID: <1429019742.16400.1.camel@mhfsdcap03>

On Tue, 2015-04-14 at 21:49 +0800, Yong Wu wrote:
> Hi Mark,
> 
> On Tue, 2015-04-14 at 11:06 +0100, Mark Rutland wrote:
> > On Tue, Apr 14, 2015 at 10:07:54AM +0100, Yong Wu wrote:
> > > Hi Mark,
> > >     Thanks very much for review. 
> > >     About the clock name should be the PoV of _this_ device. Could you
> > > help check below?
> > > 
> > > On Fri, 2015-03-06 at 11:13 +0000, Mark Rutland wrote:
> > > > On Fri, Mar 06, 2015 at 10:48:18AM +0000, yong.wu at mediatek.com wrote:
> > > > > From: Yong Wu <yong.wu at mediatek.com>
> > > > > 
> > > > > This patch add smi binding document.
> > > > 
> > > > Please move binding documents to the start of the series. It makes
> > > > things far easier to review.
> > > >  
> > > > What does "larb" mean? It would be nice for the intorductory paragraph
> > > > in this file to explain.
> > > > 
> > > > > +- reg : the register of each local arbiter
> > > > > +- clocks : the clocks of each local arbiter
> > > > > +- clock-name: larb_sub*(3 clockes at most)
> > > > 
> > > > The names required _must_ be specified here, or clock-names is
> > > > pointless.
> > > > 
> > > > The clock names should be from the PoV of _this_ device (i.e. they
> > > > should be the names of the inputs) not from the PoV of the provider
> > > > (i.e. they should not be the names of the outputs from the provider).
> > > > 
> > > > Mark.
> > > > 
> > >      After we check with our SMI Designer. Every SMI local arbiter need
> > > two clocks, which is called  APB clocks and SMI clock.
> > >      APB clock : Advanced Peripheral Bus Clock. It is the clock for
> > > setting the register of local arbiter.
> > >      SMI clock : Smart Multimedia Interface Clock, It is the clock for
> > > transfering the data and command. 
> > > 
> > >      And all the local arbiters need the smi common clock, so we
> > > separate it. 
> > > 
> > >      Then I prepare to design the smi the dtsi like this: 
> > > 
> > >       smi_common:smi at 14022000 {
> > >                  compatible = ?mediate, mt8173-smi?;
> > >                  reg = <0 0x14022000 0 0x1000>;
> > >                  clocks = <&mmsys MM_SMI_COMMON>;
> > >                  clocks-names = ?smi_common?;
> > >       };
> > > 
> > >       larb0: larb at 14021000 {
> > >                  compatible = ?mediate, mt8173-smi-larb?;
> > >                  reg = <0 0x14021000 0 0x1000>;
> > >                  smi = <&smi_common>;
> > >                  clocks = <&mmsys MM_SMI_LARB0>, 
> > > 		 	<&mmsys MM_SMI_LARB0>;
> > >                  clocks-names = ?apb_clk?, ?smi_clk?;
> > >      };
> > > 
> > >      larb1: larb at 16010000 {
> > >                  compatible = ?mediate, mt8173-smi-larb?;
> > >                  reg = <0 0x16010000 0 0x1000>;
> > >                  smi = <&smi_common>;
> > >                  clocks = <&vdecsys VDEC_CKEN>, 
> > > 			 <&mmsys VDEC_LARB_CKEN>;
> > >                  clocks-names = ?apb_clk?, ?smi_clk?;
> > >       };
> > >       ? 
> > >      In some local arbiter, the source clock of the APB clock and the
> > > SMI clock may be the same, like larb0. so the two clocks are the same.
> > > And they may be different in other local arbiteres, like larb1.      
> > > 
> > >      If it is designed like this, is it ok?
> > 
> > That looks pretty good; the clocks and names on the larb nodes seem
> > sensible.
> > 
> > The naming of the "smi_common" clock on the smi_common node looks a bit
> > odd though. Is that really what the clock input is called?
> > 
> > Mark.
>      After check with DE, the smi_common clock also have its APB clock
> and the smi clock(they have the same clock source).
>     And I prepare to delete "_clk" in all the clock-names.
>     So it may be like this:
>          smi_common:smi at 14022000 {
>                  compatible = ?mediate, mt8173-smi?;
>                   reg = <0 0x14022000 0 0x1000>;
>                   clocks = <&mmsys MM_SMI_COMMON>, 
> 			   <&mmsys MM_SMI_COMMON>;
>                   clocks-names = ?apk?,"smi";
>         };
>      How about this?
      Sorry, I wrote wrong, it should be 
      clock-names = ?apb?,"smi";
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek




From mark.rutland at arm.com  Tue Apr 14 06:56:47 2015
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 14 Apr 2015 14:56:47 +0100
Subject: [PATCH 3/5] dt-bindings: mediatek: Add smi dts binding
In-Reply-To: <1429019389.16264.5.camel@mhfsdcap03>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-4-git-send-email-yong.wu@mediatek.com>
 <20150306111338.GD8700@leverpostej>
 <1429002474.14855.7.camel@mhfsdcap03>
 <20150414100657.GB28709@leverpostej>
 <1429019389.16264.5.camel@mhfsdcap03>
Message-ID: <20150414135647.GG28709@leverpostej>

> > >       smi_common:smi at 14022000 {
> > >                  compatible = ?mediate, mt8173-smi?;
> > >                  reg = <0 0x14022000 0 0x1000>;
> > >                  clocks = <&mmsys MM_SMI_COMMON>;
> > >                  clocks-names = ?smi_common?;
> > >       };
> > > 
> > >       larb0: larb at 14021000 {
> > >                  compatible = ?mediate, mt8173-smi-larb?;
> > >                  reg = <0 0x14021000 0 0x1000>;
> > >                  smi = <&smi_common>;
> > >                  clocks = <&mmsys MM_SMI_LARB0>, 
> > > 		 	<&mmsys MM_SMI_LARB0>;
> > >                  clocks-names = ?apb_clk?, ?smi_clk?;
> > >      };
> > > 
> > >      larb1: larb at 16010000 {
> > >                  compatible = ?mediate, mt8173-smi-larb?;
> > >                  reg = <0 0x16010000 0 0x1000>;
> > >                  smi = <&smi_common>;
> > >                  clocks = <&vdecsys VDEC_CKEN>, 
> > > 			 <&mmsys VDEC_LARB_CKEN>;
> > >                  clocks-names = ?apb_clk?, ?smi_clk?;
> > >       };
> > >       ? 
> > >      In some local arbiter, the source clock of the APB clock and the
> > > SMI clock may be the same, like larb0. so the two clocks are the same.
> > > And they may be different in other local arbiteres, like larb1.      
> > > 
> > >      If it is designed like this, is it ok?
> > 
> > That looks pretty good; the clocks and names on the larb nodes seem
> > sensible.
> > 
> > The naming of the "smi_common" clock on the smi_common node looks a bit
> > odd though. Is that really what the clock input is called?
> > 
> > Mark.
>      After check with DE, the smi_common clock also have its APB clock
> and the smi clock(they have the same clock source).
>     And I prepare to delete "_clk" in all the clock-names.
>     So it may be like this:
>          smi_common:smi at 14022000 {
>                  compatible = ?mediate, mt8173-smi?;
>                     reg = <0 0x14022000 0 0x1000>;
>                   clocks = <&mmsys MM_SMI_COMMON>, 
> 			   <&mmsys MM_SMI_COMMON>;
>                   clocks-names = ?apk?,"smi";
>         };
>      How about this?

That looks fine to me. I assume "apk" should be "apb" in the last
example.

Mark.


From tfiga at google.com  Tue Apr 14 19:20:51 2015
From: tfiga at google.com (Tomasz Figa)
Date: Wed, 15 Apr 2015 11:20:51 +0900
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <1428993067.13552.14.camel@mhfsdcap03>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03>
 <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
 <1428993067.13552.14.camel@mhfsdcap03>
Message-ID: <CAAFQd5Db+DacQYa1pdr=w5JpU76AYa-Xhd20wHBF=F6m=Efokw@mail.gmail.com>

On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu <yong.wu at mediatek.com> wrote:
>> >>
>> >> > +
>> >> > +       piommu->protect_va = devm_kmalloc(piommu->dev, MTK_PROTECT_PA_ALIGN*2,
>> >>
>> >> style: Operators like * should have space on both sides.
>> >>
>> >> > +                                         GFP_KERNEL);
>> >>
>> >> Shouldn't dma_alloc_coherent() be used for this?
>> >      We don't care the data in it. I think they are the same. Could you
>> > help tell me why dma_alloc_coherent may be better.
>>
>> Can you guarantee that at the time you allocate the memory using
>> devm_kmalloc() the memory is not dirty (i.e. some write back data are
>> stored in CPU cache) and is not going to be written back in some time,
>> overwriting data put there by IOMMU hardware?
>>
> As I noted in the function "mtk_iommu_hw_init":
>
>        /* protect memory,HW will write here while translation fault */
>        protectpa = __virt_to_phys(piommu->protect_va);
>
>      We don?t care the content of this buffer, It is ok even though its
> data is dirty.
>     It seem to be a the protect memory. While a translation fault
> happened, The iommu HW will overwrite here instead of writing to the
> fault physical address which may be 0 or some random address.
>

Do you mean that it's just a dummy page for hardware behind the IOMMU
to access when the mapping is not available? How would that work with
potential on demand paging when the hardware needs to be blocked until
the mapping is created?

Best regards,
Tomasz


From yong.wu at mediatek.com  Wed Apr 15 00:06:07 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Wed, 15 Apr 2015 15:06:07 +0800
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <CAAFQd5Db+DacQYa1pdr=w5JpU76AYa-Xhd20wHBF=F6m=Efokw@mail.gmail.com>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03>
 <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
 <1428993067.13552.14.camel@mhfsdcap03>
 <CAAFQd5Db+DacQYa1pdr=w5JpU76AYa-Xhd20wHBF=F6m=Efokw@mail.gmail.com>
Message-ID: <1429081567.16400.16.camel@mhfsdcap03>

On Wed, 2015-04-15 at 11:20 +0900, Tomasz Figa wrote:
> On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu <yong.wu at mediatek.com> wrote:
> >> >>
> >> >> > +
> >> >> > +       piommu->protect_va = devm_kmalloc(piommu->dev, MTK_PROTECT_PA_ALIGN*2,
> >> >>
> >> >> style: Operators like * should have space on both sides.
> >> >>
> >> >> > +                                         GFP_KERNEL);
> >> >>
> >> >> Shouldn't dma_alloc_coherent() be used for this?
> >> >      We don't care the data in it. I think they are the same. Could you
> >> > help tell me why dma_alloc_coherent may be better.
> >>
> >> Can you guarantee that at the time you allocate the memory using
> >> devm_kmalloc() the memory is not dirty (i.e. some write back data are
> >> stored in CPU cache) and is not going to be written back in some time,
> >> overwriting data put there by IOMMU hardware?
> >>
> > As I noted in the function "mtk_iommu_hw_init":
> >
> >        /* protect memory,HW will write here while translation fault */
> >        protectpa = __virt_to_phys(piommu->protect_va);
> >
> >      We don?t care the content of this buffer, It is ok even though its
> > data is dirty.
> >     It seem to be a the protect memory. While a translation fault
> > happened, The iommu HW will overwrite here instead of writing to the
> > fault physical address which may be 0 or some random address.
> >
> 
> Do you mean that it's just a dummy page for hardware behind the IOMMU
> to access when the mapping is not available? How would that work with
> potential on demand paging when the hardware needs to be blocked until
> the mapping is created?
> 
> Best regards,
> Tomasz
 1. YES
 2. Sorry. Our iommu HW can not support this right now. The HW can not
be blocked until the mapping is created.
    If the page is not ready, we can not get the physical address, then
How to fill the pagetable for that memory. I think the dma&iommu may
guaranty it?




From tfiga at google.com  Wed Apr 15 00:41:17 2015
From: tfiga at google.com (Tomasz Figa)
Date: Wed, 15 Apr 2015 16:41:17 +0900
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <1429081567.16400.16.camel@mhfsdcap03>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03>
 <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
 <1428993067.13552.14.camel@mhfsdcap03>
 <CAAFQd5Db+DacQYa1pdr=w5JpU76AYa-Xhd20wHBF=F6m=Efokw@mail.gmail.com>
 <1429081567.16400.16.camel@mhfsdcap03>
Message-ID: <CAAFQd5A2FgsbusEbxVVqSeC7hY=Ewe-YbJ7bbvk-SjpSC==xDw@mail.gmail.com>

On Wed, Apr 15, 2015 at 4:06 PM, Yong Wu <yong.wu at mediatek.com> wrote:
> On Wed, 2015-04-15 at 11:20 +0900, Tomasz Figa wrote:
>> On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu <yong.wu at mediatek.com> wrote:
>> >> >>
>> >> >> > +
>> >> >> > +       piommu->protect_va = devm_kmalloc(piommu->dev, MTK_PROTECT_PA_ALIGN*2,
>> >> >>
>> >> >> style: Operators like * should have space on both sides.
>> >> >>
>> >> >> > +                                         GFP_KERNEL);
>> >> >>
>> >> >> Shouldn't dma_alloc_coherent() be used for this?
>> >> >      We don't care the data in it. I think they are the same. Could you
>> >> > help tell me why dma_alloc_coherent may be better.
>> >>
>> >> Can you guarantee that at the time you allocate the memory using
>> >> devm_kmalloc() the memory is not dirty (i.e. some write back data are
>> >> stored in CPU cache) and is not going to be written back in some time,
>> >> overwriting data put there by IOMMU hardware?
>> >>
>> > As I noted in the function "mtk_iommu_hw_init":
>> >
>> >        /* protect memory,HW will write here while translation fault */
>> >        protectpa = __virt_to_phys(piommu->protect_va);
>> >
>> >      We don?t care the content of this buffer, It is ok even though its
>> > data is dirty.
>> >     It seem to be a the protect memory. While a translation fault
>> > happened, The iommu HW will overwrite here instead of writing to the
>> > fault physical address which may be 0 or some random address.
>> >
>>
>> Do you mean that it's just a dummy page for hardware behind the IOMMU
>> to access when the mapping is not available? How would that work with
>> potential on demand paging when the hardware needs to be blocked until
>> the mapping is created?
>>
>> Best regards,
>> Tomasz
>  1. YES
>  2. Sorry. Our iommu HW can not support this right now. The HW can not
> be blocked until the mapping is created.

OK, that explains it. Well, then I guess this is necessary and
contents of that memory don't matter that much. (Although, this might
be a minor security issue, because the faulting hardware would get
access to some data previously stored by kernel code. Not sure how
much of a threat would that be, though.)

>     If the page is not ready, we can not get the physical address, then
> How to fill the pagetable for that memory. I think the dma&iommu may
> guaranty it?

If your hardware can't block until the mapping is created then what
you do currently seems to be the only option. (+/- the missing cache
maintenance at initialization)

Best regards,
Tomasz


From matthias.bgg at gmail.com  Wed Apr 15 08:11:27 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Wed, 15 Apr 2015 17:11:27 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <20150414115702.GX9742@pengutronix.de>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
 <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
 <20150414115702.GX9742@pengutronix.de>
Message-ID: <CABuKBe+MnmL47FB2FhN=RRKEZV4tR3OyVTTpWfkTYQ4zSZP22Q@mail.gmail.com>

2015-04-14 13:57 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Tue, Apr 14, 2015 at 01:01:30PM +0200, Matthias Brugger wrote:
>> Hi Sascha,
>>
>> 2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> > Hi Matthias,
>> >
>> > On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
>> >> Hi Sascha,
>> >>
>> >>
>> >> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> >> >
>> >> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
>> >> >
>> >> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
>> >> >
>> >> > are available in the git repository at:
>> >> >
>> >> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
>> >> >
>> >> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
>> >> >
>> >> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
>> >> >
>> >> > ----------------------------------------------------------------
>> >> > This patchset contains the initial common clock support for Mediatek SoCs.
>> >> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
>> >> > and clock gates.
>> >>
>> >> I tried the patch set on my mt8135 eval board. I used the dts bindings
>> >> from a former version of this set [1], but it does not boot the board
>> >> (based on v4.0-rc7).
>> >> Do you have any hint, what is happening, or are the bindings wrong?
>> >
>> > I just tried on a v4.0 with
>> > - this series applied
>> > - the dts patch applied (which is still up-to-date)
>> > - multi_v7_defconfig
>> >
>> > And it still works. What do you mean with "does not boot the board"? No
>> > console output? Could you try with earlyprintk?
>>
>> The probelms I see is, that with the clock patches, I'm not able to
>> boot into a initramfs [1].
>> Whereas if I just comment topckgen and preicfg in the dts, I'm able to
>> get the a serial console of my initramfs [2].
>>
>> I wonder if you are able to get serial console from the initramfs with
>> the clock patches + dts patch?
>
> So you get kernel messages but no output from initramfs? In this case
> the kernel disables the unused clocks in a late_initcall. The UART
> driver still uses the dummy clock provided in the dtsi, so the real
> UART clk gets disabled in the initcall. Try passing clk_ignore_unused to
> the kernel

OK, I can boot to the initramfs with this kernel parameter, but it
fails to boot, when I change the uart clock. I suppose that PERI_UART3
for debug port uart3 should be fine, but it looks like it doesn't
work.
I can see on the mt6589 datasheet that you have a register
PERI_UART_CK_SOURCE_SEL where you can decide if you want a 26 MHz or a
52 MHz clock for the UART block.
Does this register exists on mt8135? If so, why is it not implemented?

-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Wed Apr 15 08:48:08 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Wed, 15 Apr 2015 17:48:08 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBe+MnmL47FB2FhN=RRKEZV4tR3OyVTTpWfkTYQ4zSZP22Q@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
 <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
 <20150414115702.GX9742@pengutronix.de>
 <CABuKBe+MnmL47FB2FhN=RRKEZV4tR3OyVTTpWfkTYQ4zSZP22Q@mail.gmail.com>
Message-ID: <CABuKBeLaUfseZU84vNmVFR3EeUhNrbrXnKeN=N6PP=abPcnjDQ@mail.gmail.com>

2015-04-15 17:11 GMT+02:00 Matthias Brugger <matthias.bgg at gmail.com>:
> 2015-04-14 13:57 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> On Tue, Apr 14, 2015 at 01:01:30PM +0200, Matthias Brugger wrote:
>>> Hi Sascha,
>>>
>>> 2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>>> > Hi Matthias,
>>> >
>>> > On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
>>> >> Hi Sascha,
>>> >>
>>> >>
>>> >> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>>> >> >
>>> >> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
>>> >> >
>>> >> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
>>> >> >
>>> >> > are available in the git repository at:
>>> >> >
>>> >> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
>>> >> >
>>> >> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
>>> >> >
>>> >> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
>>> >> >
>>> >> > ----------------------------------------------------------------
>>> >> > This patchset contains the initial common clock support for Mediatek SoCs.
>>> >> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
>>> >> > and clock gates.
>>> >>
>>> >> I tried the patch set on my mt8135 eval board. I used the dts bindings
>>> >> from a former version of this set [1], but it does not boot the board
>>> >> (based on v4.0-rc7).
>>> >> Do you have any hint, what is happening, or are the bindings wrong?
>>> >
>>> > I just tried on a v4.0 with
>>> > - this series applied
>>> > - the dts patch applied (which is still up-to-date)
>>> > - multi_v7_defconfig
>>> >
>>> > And it still works. What do you mean with "does not boot the board"? No
>>> > console output? Could you try with earlyprintk?
>>>
>>> The probelms I see is, that with the clock patches, I'm not able to
>>> boot into a initramfs [1].
>>> Whereas if I just comment topckgen and preicfg in the dts, I'm able to
>>> get the a serial console of my initramfs [2].
>>>
>>> I wonder if you are able to get serial console from the initramfs with
>>> the clock patches + dts patch?
>>
>> So you get kernel messages but no output from initramfs? In this case
>> the kernel disables the unused clocks in a late_initcall. The UART
>> driver still uses the dummy clock provided in the dtsi, so the real
>> UART clk gets disabled in the initcall. Try passing clk_ignore_unused to
>> the kernel
>
> OK, I can boot to the initramfs with this kernel parameter, but it
> fails to boot, when I change the uart clock. I suppose that PERI_UART3
> for debug port uart3 should be fine, but it looks like it doesn't
> work.
> I can see on the mt6589 datasheet that you have a register
> PERI_UART_CK_SOURCE_SEL where you can decide if you want a 26 MHz or a
> 52 MHz clock for the UART block.
> Does this register exists on mt8135? If so, why is it not implemented?

I found that PERI_UARTx_CK is connected to axi_sel but should be
connected to uart_sel. Like this I'm able to reach to initramfs
console, but the baud rate values are screwed up.
As uart_sel is at 52 MHz, I suppose we need to change the entries in
PERI_UART_CK_SOURCE_SEL.

Cheers,
Matthias

-- 
motzblog.wordpress.com


From computersforpeace at gmail.com  Wed Apr 15 10:59:36 2015
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 15 Apr 2015 10:59:36 -0700
Subject: [PATCH 13/13] thermal: of: implement .set_trips for device tree
 thermal zones
In-Reply-To: <20150413063018.GT9742@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-14-git-send-email-s.hauer@pengutronix.de>
 <20150407024307.GH4648@localhost.localdomain>
 <20150413063018.GT9742@pengutronix.de>
Message-ID: <20150415175936.GR32500@ld-irv-0074>

On Mon, Apr 13, 2015 at 08:30:18AM +0200, Sascha Hauer wrote:
> On Mon, Apr 06, 2015 at 07:43:08PM -0700, Eduardo Valentin wrote:
> > On Thu, Mar 26, 2015 at 04:54:00PM +0100, Sascha Hauer wrote:
> > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > > ---
> > >  drivers/thermal/of-thermal.c | 12 ++++++++++++
> > >  include/linux/thermal.h      |  1 +
> > >  2 files changed, 13 insertions(+)
> > 
> > Can you please include at least one user of this call back in your patch
> > series?
> 
> Thanks for the comments on this series. I'll address them in the next
> round. The user for this callback is not yet ready to be posted. I'll
> try and move this patch to the end of the series so that the series can
> be applied without this one.

I'm actually interested in this patch, as I am developing a thermal
sensor driver that has hardware-assisted temperature-trip interrupts.
I'm testing out your patches now, and will probably end up using them on
my local tree. With help of this (and a few other changes I need to
make), my driver should be ready to post soon.

So, I'll try to post my driver soon as an example, if you'd like. I'd
also appreciate a CC on any future revisions, if you don't mind. I'm
subscribed to the list, but it's not always easy to pick out the signal
from the noise.

Thanks,
Brian

P.S. Time for a mild complaint: I think it seems to be a bit of a plague
in the thermal subsystem; there are API's, and even user-space ABI's
(!!) that have no in-kernel users! e.g., generate_netlink_event()
http://article.gmane.org/gmane.linux.power-management.general/58685


From computersforpeace at gmail.com  Wed Apr 15 11:06:48 2015
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 15 Apr 2015 11:06:48 -0700
Subject: [PATCH 12/13] thermal: Add support for hardware-tracked trip
 points
In-Reply-To: <1427385240-6086-13-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-13-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150415180648.GS32500@ld-irv-0074>

Hi Sascha,

On Thu, Mar 26, 2015 at 04:53:59PM +0100, Sascha Hauer wrote:
> This adds support for hardware-tracked trip points to the device tree
> thermal sensor framework.
> 
> The framework supports an arbitrary number of trip points. Whenever
> the current temperature is updated, the trip points immediately
> below and above the current temperature are found. A .set_trips
> callback is then called with the temperatures. If there is no trip
> point above or below the current temperature, the passed trip
> temperature will be ULONG_MAX or 0 respectively. In this callback,
> the driver should program the hardware such that it is notified
> when either of these trip points are triggered. When a trip point
> is triggered, the driver should call `thermal_zone_device_update'
> for the respective thermal zone. This will cause the trip points
> to be updated again.
> 
> If .set_trips is not implemented, the framework behaves as before.
> 
> This patch is based on an earlier version from Mikko Perttunen
> <mikko.perttunen at kapsi.fi>
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/thermal/thermal_core.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/thermal.h        |  3 +++
>  2 files changed, 44 insertions(+)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index dcdf45e..7138f8f 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -434,6 +434,45 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
>  }
>  EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
>  
> +static void thermal_zone_set_trips(struct thermal_zone_device *tz)
> +{
> +	unsigned long low = 0;
> +	unsigned long high = ULONG_MAX;
> +	unsigned long trip_temp, hysteresis;
> +	unsigned long temp = tz->temperature;
> +	int i;
> +
> +	if (!tz->ops->set_trips)
> +		return;
> +
> +	/* No need to change trip points */
> +	if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
> +		return;

I see that you don't actually initialize prev_{low,high}_trip during
device initialization, so they both start out as zero. I suppose that
works here, mostly by coincidence, because it means we'll still always
recalculate trip points the first time, but might it make sense to
explicitly initialize them to:
  low = ULONG_MAX
  high = 0
at init time? (Or, if these change to integer: INT_MAX and -INT_MAX?)

Thanks,
Brian

> +
> +	for (i = 0; i < tz->trips; i++) {
> +		unsigned long trip_low;
> +
> +		tz->ops->get_trip_temp(tz, i, &trip_temp);
> +		tz->ops->get_trip_hyst(tz, i, &hysteresis);
> +
> +		trip_low = trip_temp - hysteresis;
> +
> +		if (trip_low < temp && trip_low > low)
> +			low = trip_low;
> +
> +		if (trip_temp > temp && trip_temp < high)
> +			high = trip_temp;
> +	}
> +
> +	tz->prev_low_trip = low;
> +	tz->prev_high_trip = high;
> +
> +	dev_dbg(&tz->device, "new temperature boundaries: %lu < x < %lu\n",
> +			low, high);
> +
> +	tz->ops->set_trips(tz, low, high);
> +}
> +
>  void thermal_zone_device_update(struct thermal_zone_device *tz)
>  {
>  	int count;
> @@ -460,6 +499,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  	dev_dbg(&tz->device, "last_temperature=%lu, current_temperature=%lu\n",
>  				tz->last_temperature, tz->temperature);
>  
> +	thermal_zone_set_trips(tz);
> +
>  	for (count = 0; count < tz->trips; count++)
>  		handle_thermal_trip(tz, count);
>  }
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index ac2897c..b870702 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
>  	int (*unbind) (struct thermal_zone_device *,
>  		       struct thermal_cooling_device *);
>  	int (*get_temp) (struct thermal_zone_device *, unsigned long *);
> +	int (*set_trips) (struct thermal_zone_device *, unsigned long, unsigned long);
>  	int (*get_mode) (struct thermal_zone_device *,
>  			 enum thermal_device_mode *);
>  	int (*set_mode) (struct thermal_zone_device *,
> @@ -183,6 +184,8 @@ struct thermal_zone_device {
>  	unsigned long temperature;
>  	unsigned long last_temperature;
>  	unsigned long emul_temperature;
> +	unsigned long prev_low_trip;
> +	unsigned long prev_high_trip;
>  	int passive;
>  	unsigned int forced_passive;
>  	const struct thermal_zone_device_ops *ops;
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From s.hauer at pengutronix.de  Thu Apr 16 06:36:35 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 16 Apr 2015 15:36:35 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBeLaUfseZU84vNmVFR3EeUhNrbrXnKeN=N6PP=abPcnjDQ@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
 <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
 <20150414115702.GX9742@pengutronix.de>
 <CABuKBe+MnmL47FB2FhN=RRKEZV4tR3OyVTTpWfkTYQ4zSZP22Q@mail.gmail.com>
 <CABuKBeLaUfseZU84vNmVFR3EeUhNrbrXnKeN=N6PP=abPcnjDQ@mail.gmail.com>
Message-ID: <20150416133635.GS9742@pengutronix.de>

On Wed, Apr 15, 2015 at 05:48:08PM +0200, Matthias Brugger wrote:
> 2015-04-15 17:11 GMT+02:00 Matthias Brugger <matthias.bgg at gmail.com>:
> > 2015-04-14 13:57 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >> On Tue, Apr 14, 2015 at 01:01:30PM +0200, Matthias Brugger wrote:
> >>> Hi Sascha,
> >>>
> >>> 2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >>> > Hi Matthias,
> >>> >
> >>> > On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
> >>> >> Hi Sascha,
> >>> >>
> >>> >>
> >>> >> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >>> >> >
> >>> >> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
> >>> >> >
> >>> >> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
> >>> >> >
> >>> >> > are available in the git repository at:
> >>> >> >
> >>> >> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
> >>> >> >
> >>> >> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
> >>> >> >
> >>> >> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
> >>> >> >
> >>> >> > ----------------------------------------------------------------
> >>> >> > This patchset contains the initial common clock support for Mediatek SoCs.
> >>> >> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> >>> >> > and clock gates.
> >>> >>
> >>> >> I tried the patch set on my mt8135 eval board. I used the dts bindings
> >>> >> from a former version of this set [1], but it does not boot the board
> >>> >> (based on v4.0-rc7).
> >>> >> Do you have any hint, what is happening, or are the bindings wrong?
> >>> >
> >>> > I just tried on a v4.0 with
> >>> > - this series applied
> >>> > - the dts patch applied (which is still up-to-date)
> >>> > - multi_v7_defconfig
> >>> >
> >>> > And it still works. What do you mean with "does not boot the board"? No
> >>> > console output? Could you try with earlyprintk?
> >>>
> >>> The probelms I see is, that with the clock patches, I'm not able to
> >>> boot into a initramfs [1].
> >>> Whereas if I just comment topckgen and preicfg in the dts, I'm able to
> >>> get the a serial console of my initramfs [2].
> >>>
> >>> I wonder if you are able to get serial console from the initramfs with
> >>> the clock patches + dts patch?
> >>
> >> So you get kernel messages but no output from initramfs? In this case
> >> the kernel disables the unused clocks in a late_initcall. The UART
> >> driver still uses the dummy clock provided in the dtsi, so the real
> >> UART clk gets disabled in the initcall. Try passing clk_ignore_unused to
> >> the kernel
> >
> > OK, I can boot to the initramfs with this kernel parameter, but it
> > fails to boot, when I change the uart clock. I suppose that PERI_UART3
> > for debug port uart3 should be fine, but it looks like it doesn't
> > work.
> > I can see on the mt6589 datasheet that you have a register
> > PERI_UART_CK_SOURCE_SEL where you can decide if you want a 26 MHz or a
> > 52 MHz clock for the UART block.
> > Does this register exists on mt8135? If so, why is it not implemented?
> 
> I found that PERI_UARTx_CK is connected to axi_sel but should be
> connected to uart_sel. Like this I'm able to reach to initramfs
> console, but the baud rate values are screwed up.
> As uart_sel is at 52 MHz, I suppose we need to change the entries in
> PERI_UART_CK_SOURCE_SEL.

I just asked the Mediatek guys for clarification, lets see what they
tell me. There is a PERI_UART_CK_SOURCE_SEL on MT8135/MT8173, I have no
idea why this is not implemented. I also don't know where the clocks I
can select in the PERI_UART_CK_SOURCE_SEL register are derived from.
It's also unclear to me how the real UART clock topology looks like.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr 16 22:22:44 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 17 Apr 2015 07:22:44 +0200
Subject: [PATCH 13/13] thermal: of: implement .set_trips for device tree
 thermal zones
In-Reply-To: <20150415175936.GR32500@ld-irv-0074>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-14-git-send-email-s.hauer@pengutronix.de>
 <20150407024307.GH4648@localhost.localdomain>
 <20150413063018.GT9742@pengutronix.de>
 <20150415175936.GR32500@ld-irv-0074>
Message-ID: <20150417052244.GA6325@pengutronix.de>

Hi Brian,

On Wed, Apr 15, 2015 at 10:59:36AM -0700, Brian Norris wrote:
> On Mon, Apr 13, 2015 at 08:30:18AM +0200, Sascha Hauer wrote:
> > On Mon, Apr 06, 2015 at 07:43:08PM -0700, Eduardo Valentin wrote:
> > > On Thu, Mar 26, 2015 at 04:54:00PM +0100, Sascha Hauer wrote:
> > > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > > > ---
> > > >  drivers/thermal/of-thermal.c | 12 ++++++++++++
> > > >  include/linux/thermal.h      |  1 +
> > > >  2 files changed, 13 insertions(+)
> > > 
> > > Can you please include at least one user of this call back in your patch
> > > series?
> > 
> > Thanks for the comments on this series. I'll address them in the next
> > round. The user for this callback is not yet ready to be posted. I'll
> > try and move this patch to the end of the series so that the series can
> > be applied without this one.
> 
> I'm actually interested in this patch, as I am developing a thermal
> sensor driver that has hardware-assisted temperature-trip interrupts.
> I'm testing out your patches now, and will probably end up using them on
> my local tree. With help of this (and a few other changes I need to
> make), my driver should be ready to post soon.
> 
> So, I'll try to post my driver soon as an example, if you'd like. I'd
> also appreciate a CC on any future revisions, if you don't mind. I'm
> subscribed to the list, but it's not always easy to pick out the signal
> from the noise.

Sure, I'll add you to Cc next round. I'm halfway through updating this
series according to the comments I received, but got distracted. I hope
to send an update next week.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Fri Apr 17 02:12:13 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 17 Apr 2015 11:12:13 +0200
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
Message-ID: <20150417091213.GM4946@pengutronix.de>

Ulf,

On Tue, Mar 31, 2015 at 02:23:06PM +0200, Ulf Hansson wrote:
> On 17 March 2015 at 04:13, Chaotian Jing <chaotian.jing at mediatek.com> wrote:
> > +
> > +       msdc_set_buswidth(host, ios->bus_width);
> > +
> > +       /* Suspend/Resume will do power off/on */
> > +       switch (ios->power_mode) {
> > +       case MMC_POWER_UP:
> > +               msdc_init_hw(host);
> > +               if (!IS_ERR(mmc->supply.vmmc)) {
> > +                       ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
> > +                                       ios->vdd);
> > +                       if (ret) {
> > +                               dev_err(host->dev, "Failed to set vmmc power!\n");
> > +                               return;
> > +                       }
> > +               }
> > +               break;
> > +       case MMC_POWER_ON:
> > +               if (!IS_ERR(mmc->supply.vqmmc)) {
> > +                       ret = regulator_enable(mmc->supply.vqmmc);
> 
> The calls to regulator_enable|disable() for the vqmmc will not be
> balanced properly here. You need a local cache variable like
> "is_enabled" to keep track of this.

Shouldn't the MMC core provide balanced hooks for this? What about
MMC_POWER_UP, can this be used for enabling regulators?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From ulf.hansson at linaro.org  Fri Apr 17 02:37:44 2015
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 17 Apr 2015 11:37:44 +0200
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <20150417091213.GM4946@pengutronix.de>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <CAPDyKFoUg1snXeOwCiKPF_daxAAfcWE0nUbRAj23Z=k9z5FCyA@mail.gmail.com>
 <20150417091213.GM4946@pengutronix.de>
Message-ID: <CAPDyKFr5NDTnx_3brksimhqGj+0Rk=tH5fLfWyRddRdPf7i6Lg@mail.gmail.com>

On 17 April 2015 at 11:12, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> Ulf,
>
> On Tue, Mar 31, 2015 at 02:23:06PM +0200, Ulf Hansson wrote:
>> On 17 March 2015 at 04:13, Chaotian Jing <chaotian.jing at mediatek.com> wrote:
>> > +
>> > +       msdc_set_buswidth(host, ios->bus_width);
>> > +
>> > +       /* Suspend/Resume will do power off/on */
>> > +       switch (ios->power_mode) {
>> > +       case MMC_POWER_UP:
>> > +               msdc_init_hw(host);
>> > +               if (!IS_ERR(mmc->supply.vmmc)) {
>> > +                       ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
>> > +                                       ios->vdd);
>> > +                       if (ret) {
>> > +                               dev_err(host->dev, "Failed to set vmmc power!\n");
>> > +                               return;
>> > +                       }
>> > +               }
>> > +               break;
>> > +       case MMC_POWER_ON:
>> > +               if (!IS_ERR(mmc->supply.vqmmc)) {
>> > +                       ret = regulator_enable(mmc->supply.vqmmc);
>>
>> The calls to regulator_enable|disable() for the vqmmc will not be
>> balanced properly here. You need a local cache variable like
>> "is_enabled" to keep track of this.
>
> Shouldn't the MMC core provide balanced hooks for this? What about
> MMC_POWER_UP, can this be used for enabling regulators?

Currently host drivers deals with vqmmc enabling/disabling, setting
voltage, etc - entirely by them selves.

Dough Anderson is working on fixing that:
http://lkml.iu.edu/hypermail/linux/kernel/1503.1/03108.html

MMC_POWER_UP is when vmmc shall be enabled.

MMC_POWER_ON is when vqmmc shall be enabled.

Kind regards
Uffe


From s.hauer at pengutronix.de  Fri Apr 17 06:45:47 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 17 Apr 2015 15:45:47 +0200
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150417134547.GN4946@pengutronix.de>

Hi Chaotian,

On Tue, Mar 17, 2015 at 11:13:52AM +0800, Chaotian Jing wrote:
> Add Mediatek MMC driver code
> 

[...]

> +	host->dev = &pdev->dev;
> +	host->mmc = mmc;
> +	/* Set host parameters to mmc */
> +	mmc->ops = &mt_msdc_ops;
> +	mmc->f_min = 260000;
> +	mmc->ocr_avail = MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33;
> +
> +	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
> +	/* MMC core transfer sizes tunable parameters */
> +	mmc->max_segs = MAX_BD_NUM;
> +	mmc->max_seg_size = 64 * 1024;

Earlier versions of this driver had 64 * 1024 - 512 here. Using 64k
breaks SD card support here. Reading the partition table still works
fine, but the next transfers fail with messages like:

mtk-msdc 11240000.mmc: msdc_request_timeout: aborting cmd/data/mrq
mtk-msdc 11240000.mmc: msdc_request_timeout: aborting mrq=ffffffc06e586860 cmd=18
mtk-msdc 11240000.mmc: msdc_request_timeout: abort data: cmd18; 136 blocks
mmcblk1: error -110 transferring data, sector 338488, nr 136, cmd response 0x900, card status 0xb00
mtk-msdc 11240000.mmc: set mclk to 0 mmc1: tried to reset card

Can you confirm this?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From broonie at kernel.org  Sat Apr 18 10:34:07 2015
From: broonie at kernel.org (Mark Brown)
Date: Sat, 18 Apr 2015 18:34:07 +0100
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
Message-ID: <20150418173407.GE26185@sirena.org.uk>

On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:

> +Each external interface (called "IO" in this driver) is presented as a
> +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> +The connection paths are configured through the device tree.

Why are these connection paths configured via device tree?  I would
expect that either there would be runtime configurability of these
things (particularly if loopback configurations within the hardware are
possible) or we'd just allocate memory interfaces to DAIs automatically
as DAIs come into use.

> +- mem-interface-playback:
> +  mem-interface-capture: property of memif, format is: <memif irq use_sram>;
> +	                 memif: which memif to be used
> +			        (defined in include/dt-bindings/sound/mtk-afe.h)
> +		         irq: which irq to be used
> +			      (defined in include/dt-bindings/sound/mtk-afe.h)
> +		         use_sram: 1 is yes, 0 is no

Again, this looks like stuff we should be able to figure out at runtime
- the use of SRAM in particular looks like something we might want to
change depending on use case.  Assuming it adds buffering then for a
VoIP application we might not want to use SRAM to minimize latency but
during music playback we might want to enable SRAM to minimize power
consumption.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150418/f9a9b312/attachment.sig>

From broonie at kernel.org  Sat Apr 18 10:37:40 2015
From: broonie at kernel.org (Mark Brown)
Date: Sat, 18 Apr 2015 18:37:40 +0100
Subject: [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control
In-Reply-To: <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
Message-ID: <20150418173740.GF26185@sirena.org.uk>

On Fri, Apr 10, 2015 at 04:14:08PM +0800, Koro Chen wrote:

> +/*
> + * The MTK AFE unit has a audio interconnect with MTK_AFE_INTERCONN_NUM_INPUT
> + * inputs and MTK_AFE_INTERCONN_NUM_OUTPUT outputs. Below table holds the
> + * register/bits to set to connect an input with an output.
> + */
> +static const struct mtk_afe_connection
> +	connections[MTK_AFE_INTERCONN_NUM_INPUT][MTK_AFE_INTERCONN_NUM_OUTPUT] = {
> +	[0][0] =   { .creg = 0x020, .cshift =  0, .sreg = 0x020, .sshift = 10},
> +	[0][1] =   { .creg = 0x020, .cshift = 16, .sreg = 0x020, .sshift = 26},

What are the constraints on using this - is it one input to one output
only or can we do mixing or duplication?  The register interface
definitely does look like something asking for runtime configuration.

It'd also be nice to have less magic numbers in the table, at least for
the indexes (which I guess correspond to some of the defines in the
headers)?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150418/28fcacb5/attachment.sig>

From broonie at kernel.org  Sat Apr 18 10:51:39 2015
From: broonie at kernel.org (Mark Brown)
Date: Sat, 18 Apr 2015 18:51:39 +0100
Subject: [RESEND RFC PATCH 3/3] ASoC: mediatek: Add AFE platform driver
In-Reply-To: <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
Message-ID: <20150418175139.GG26185@sirena.org.uk>

On Fri, Apr 10, 2015 at 04:14:09PM +0800, Koro Chen wrote:

> +	if (memif->use_sram) {
> +		struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
> +		int size = params_buffer_bytes(params);
> +
> +		memif->buffer_size = size;
> +		memif->phys_buf_addr = afe->sram_phy_address;
> +
> +		dma_buf->bytes = size;
> +		dma_buf->area = (unsigned char *)afe->sram_address;
> +		dma_buf->addr = afe->sram_phy_address;
> +		dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
> +		dma_buf->dev.dev = substream->pcm->card->dev;
> +		snd_pcm_set_runtime_buffer(substream, dma_buf);
> +	} else {
> +		ret = snd_pcm_lib_malloc_pages(substream,
> +					       params_buffer_bytes(params));
> +		if (ret < 0)
> +			return ret;
> +
> +		memif->phys_buf_addr = substream->runtime->dma_addr;
> +		memif->buffer_size = substream->runtime->dma_bytes;
> +	}

Ah, so the SRAM is directly memory mappable.  Nice.  But we have a
limited amount of it so need to allocate it to a device somehow based on
some factor I guess?

> +static int mtk_afe_set_adda_dac_out(struct mtk_afe *afe, uint32_t rate)
> +{
> +	u32 audio_i2s_dac = 0;
> +	u32 con0, con1;
> +
> +	/* set dl src2 */
> +	con0 = (mtk_afe_adda_fs(rate) << 28) | (0x03 << 24) | (0x03 << 11);
> +
> +	/* 8k or 16k voice mode */
> +	if (con0 == 0 || con0 == 3)
> +		con0 |= 0x01 << 5;

This all looks a bit magic, some defines would not go amiss here.

> +	/* SA suggests to apply -0.3db to audio/speech path */
> +	con0 = con0 | (0x01 << 1);
> +	con1 = 0xf74f0000;

More magic numbers!  This also suggests that there is a volume control
lurking in here which could usefully be exposed to applications?

> +static void mtk_afe_pmic_shutdown(struct mtk_afe *afe,
> +				  struct snd_pcm_substream *substream)
> +{
> +	/* output */
> +	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 1, 0);
> +	regmap_update_bits(afe->regmap, AFE_I2S_CON1, 1, 0);
> +
> +	/* input */
> +	regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 1, 0);
> +	/* disable ADDA */
> +	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, 1, false);
> +}

This is looking like exposing the routing and using DAPM might save a
bunch of code?  Overall my main thought looking at the code here and
what the hardware was described as doing is that it'd all be simpler if
it were a DPCM based thing using DAPM for power.  I think I'd like to
see a strong reason for not using at least DPCM.

> +		if (rate == MTK_AFE_I2S_RATE_8K)
> +			voice_mode = 0;
> +		else if (rate == MTK_AFE_I2S_RATE_16K)
> +			voice_mode = 1;
> +		else if (rate == MTK_AFE_I2S_RATE_32K)
> +			voice_mode = 2;
> +		else if (rate == MTK_AFE_I2S_RATE_48K)
> +			voice_mode = 3;

This should be a switch statement.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150418/ca74b09e/attachment.sig>

From chaotian.jing at mediatek.com  Sat Apr 18 20:22:41 2015
From: chaotian.jing at mediatek.com (chaotian.jing)
Date: Sun, 19 Apr 2015 11:22:41 +0800
Subject: [PATCH v2 2/5] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <20150417134547.GN4946@pengutronix.de>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-3-git-send-email-chaotian.jing@mediatek.com>
 <20150417134547.GN4946@pengutronix.de>
Message-ID: <1429413761.16027.2.camel@mhfsdcap03>

Dear Sascha,


On Fri, 2015-04-17 at 15:45 +0200, Sascha Hauer wrote:
> Hi Chaotian,
> 
> On Tue, Mar 17, 2015 at 11:13:52AM +0800, Chaotian Jing wrote:
> > Add Mediatek MMC driver code
> > 
> 
> [...]
> 
> > +	host->dev = &pdev->dev;
> > +	host->mmc = mmc;
> > +	/* Set host parameters to mmc */
> > +	mmc->ops = &mt_msdc_ops;
> > +	mmc->f_min = 260000;
> > +	mmc->ocr_avail = MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33;
> > +
> > +	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
> > +	/* MMC core transfer sizes tunable parameters */
> > +	mmc->max_segs = MAX_BD_NUM;
> > +	mmc->max_seg_size = 64 * 1024;
> 
> Earlier versions of this driver had 64 * 1024 - 512 here. Using 64k
> breaks SD card support here. Reading the partition table still works
> fine, but the next transfers fail with messages like:
> 
> mtk-msdc 11240000.mmc: msdc_request_timeout: aborting cmd/data/mrq
> mtk-msdc 11240000.mmc: msdc_request_timeout: aborting mrq=ffffffc06e586860 cmd=18
> mtk-msdc 11240000.mmc: msdc_request_timeout: abort data: cmd18; 136 blocks
> mmcblk1: error -110 transferring data, sector 338488, nr 136, cmd response 0x900, card status 0xb00
> mtk-msdc 11240000.mmc: set mclk to 0 mmc1: tried to reset card
> 
> Can you confirm this?
> 
Yes, it will be fixed at next revision.
Thx!
> Sascha
> 




From s.hauer at pengutronix.de  Sun Apr 19 21:37:47 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 20 Apr 2015 06:37:47 +0200
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150418173407.GE26185@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
Message-ID: <20150420043747.GH6325@pengutronix.de>

On Sat, Apr 18, 2015 at 06:34:07PM +0100, Mark Brown wrote:
> On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:
> 
> > +Each external interface (called "IO" in this driver) is presented as a
> > +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> > +The connection paths are configured through the device tree.
> 
> Why are these connection paths configured via device tree?  I would
> expect that either there would be runtime configurability of these
> things (particularly if loopback configurations within the hardware are
> possible) or we'd just allocate memory interfaces to DAIs automatically
> as DAIs come into use.

There is a crossbar switch between the memory interfaces and the DAIs.
Not every connection is possible, so not every memory interface can be
used for every DAI. An algorithm choosing a suitable memory interface
must be quite clever, complicated and also SoC dependent (the same but
different hardware is used on MT8135 aswell), so I thought offering a
static configuration via device tree is a good start. Should there be
runtime configuration possible later the device tree settings could
provide a good default.

> 
> > +- mem-interface-playback:
> > +  mem-interface-capture: property of memif, format is: <memif irq use_sram>;
> > +	                 memif: which memif to be used
> > +			        (defined in include/dt-bindings/sound/mtk-afe.h)
> > +		         irq: which irq to be used
> > +			      (defined in include/dt-bindings/sound/mtk-afe.h)
> > +		         use_sram: 1 is yes, 0 is no
> 
> Again, this looks like stuff we should be able to figure out at runtime
> - the use of SRAM in particular looks like something we might want to
> change depending on use case.  Assuming it adds buffering then for a
> VoIP application we might not want to use SRAM to minimize latency but
> during music playback we might want to enable SRAM to minimize power
> consumption.

That's exactly the usecase. How could such a runtime configurability
look like? sysfs? Or something based on the buffer sizes?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr 19 21:50:17 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 20 Apr 2015 06:50:17 +0200
Subject: [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control
In-Reply-To: <20150418173740.GF26185@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
 <20150418173740.GF26185@sirena.org.uk>
Message-ID: <20150420045017.GI6325@pengutronix.de>

On Sat, Apr 18, 2015 at 06:37:40PM +0100, Mark Brown wrote:
> On Fri, Apr 10, 2015 at 04:14:08PM +0800, Koro Chen wrote:
> 
> > +/*
> > + * The MTK AFE unit has a audio interconnect with MTK_AFE_INTERCONN_NUM_INPUT
> > + * inputs and MTK_AFE_INTERCONN_NUM_OUTPUT outputs. Below table holds the
> > + * register/bits to set to connect an input with an output.
> > + */
> > +static const struct mtk_afe_connection
> > +	connections[MTK_AFE_INTERCONN_NUM_INPUT][MTK_AFE_INTERCONN_NUM_OUTPUT] = {
> > +	[0][0] =   { .creg = 0x020, .cshift =  0, .sreg = 0x020, .sshift = 10},
> > +	[0][1] =   { .creg = 0x020, .cshift = 16, .sreg = 0x020, .sshift = 26},
> 
> What are the constraints on using this - is it one input to one output
> only or can we do mixing or duplication?  The register interface
> definitely does look like something asking for runtime configuration.
> 
> It'd also be nice to have less magic numbers in the table, at least for
> the indexes (which I guess correspond to some of the defines in the
> headers)?

With defines the above two lines would become something like:

#define AFE_CONN0		0x20

#define CONN0_I00_O00_S		0
...
#define CONN0_I00_O00_R		10
...
#define CONN0_I00_O01_s		16
...
#define CONN0_I00_O01_S		26

[0][0] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O00_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O00_R },
[0][1] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O01_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O01_S },

For the registers we could use defines, but I think using defines for
the shifts doesn't add much value given they are only used once.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From koro.chen at mediatek.com  Sun Apr 19 23:22:24 2015
From: koro.chen at mediatek.com (Koro Chen)
Date: Mon, 20 Apr 2015 14:22:24 +0800
Subject: [RESEND RFC PATCH 3/3] ASoC: mediatek: Add AFE platform driver
In-Reply-To: <20150418175139.GG26185@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
 <20150418175139.GG26185@sirena.org.uk>
Message-ID: <1429510944.30743.36.camel@mtksdaap41>

On Sat, 2015-04-18 at 18:51 +0100, Mark Brown wrote:
> On Fri, Apr 10, 2015 at 04:14:09PM +0800, Koro Chen wrote:
> 
> > +	if (memif->use_sram) {
> > +		struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
> > +		int size = params_buffer_bytes(params);
> > +
> > +		memif->buffer_size = size;
> > +		memif->phys_buf_addr = afe->sram_phy_address;
> > +
> > +		dma_buf->bytes = size;
> > +		dma_buf->area = (unsigned char *)afe->sram_address;
> > +		dma_buf->addr = afe->sram_phy_address;
> > +		dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
> > +		dma_buf->dev.dev = substream->pcm->card->dev;
> > +		snd_pcm_set_runtime_buffer(substream, dma_buf);
> > +	} else {
> > +		ret = snd_pcm_lib_malloc_pages(substream,
> > +					       params_buffer_bytes(params));
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		memif->phys_buf_addr = substream->runtime->dma_addr;
> > +		memif->buffer_size = substream->runtime->dma_bytes;
> > +	}
> 
> Ah, so the SRAM is directly memory mappable.  Nice.  But we have a
> limited amount of it so need to allocate it to a device somehow based on
> some factor I guess?
Yes, actually SRAM is only used for the main playback path (which is
memif "DL1") to achieve low power in real use case. Maybe you think it's
better to not describe this in the device tree, but to choose SRAM
automatically if memif "DL1" is chosen?
> 
> > +static int mtk_afe_set_adda_dac_out(struct mtk_afe *afe, uint32_t rate)
> > +{
> > +	u32 audio_i2s_dac = 0;
> > +	u32 con0, con1;
> > +
> > +	/* set dl src2 */
> > +	con0 = (mtk_afe_adda_fs(rate) << 28) | (0x03 << 24) | (0x03 << 11);
> > +
> > +	/* 8k or 16k voice mode */
> > +	if (con0 == 0 || con0 == 3)
> > +		con0 |= 0x01 << 5;
> 
> This all looks a bit magic, some defines would not go amiss here.
> 
> > +	/* SA suggests to apply -0.3db to audio/speech path */
> > +	con0 = con0 | (0x01 << 1);
> > +	con1 = 0xf74f0000;
> 
> More magic numbers!  This also suggests that there is a volume control
> lurking in here which could usefully be exposed to applications?
> 
Sorry, I will fix these magic numbers.
It is actually not a real volume control and not that suitable for
application control because it cannot be changed in runtime; its value
is fixed and was decided off-lined by experiment that can have best
audio quality when using with our proprietary codec (not for I2S)

> > +static void mtk_afe_pmic_shutdown(struct mtk_afe *afe,
> > +				  struct snd_pcm_substream *substream)
> > +{
> > +	/* output */
> > +	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 1, 0);
> > +	regmap_update_bits(afe->regmap, AFE_I2S_CON1, 1, 0);
> > +
> > +	/* input */
> > +	regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 1, 0);
> > +	/* disable ADDA */
> > +	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, 1, false);
> > +}
> 
> This is looking like exposing the routing and using DAPM might save a
> bunch of code?  Overall my main thought looking at the code here and
> what the hardware was described as doing is that it'd all be simpler if
> it were a DPCM based thing using DAPM for power.  I think I'd like to
> see a strong reason for not using at least DPCM.
Thank you very much for mentioning the DPCM. I didn't know much about
DPCM and I will definitely study and check if it is suitable for our HW.
> 
> > +		if (rate == MTK_AFE_I2S_RATE_8K)
> > +			voice_mode = 0;
> > +		else if (rate == MTK_AFE_I2S_RATE_16K)
> > +			voice_mode = 1;
> > +		else if (rate == MTK_AFE_I2S_RATE_32K)
> > +			voice_mode = 2;
> > +		else if (rate == MTK_AFE_I2S_RATE_48K)
> > +			voice_mode = 3;
> 
> This should be a switch statement.




From s.hauer at pengutronix.de  Sun Apr 19 23:49:10 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 20 Apr 2015 08:49:10 +0200
Subject: [PATCH v2 3/5] mmc: mediatek: Add PM support for MMC driver
In-Reply-To: <1426562035-16709-4-git-send-email-chaotian.jing@mediatek.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-4-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150420064910.GO4946@pengutronix.de>

On Tue, Mar 17, 2015 at 11:13:53AM +0800, Chaotian Jing wrote:
> Add PM support for Mediatek MMC driver
> 
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  drivers/mmc/host/mtk-sd.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 93 insertions(+), 1 deletion(-)
> 
> @@ -1003,6 +1042,8 @@ static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
>  
>  	if (!IS_ERR(mmc->supply.vqmmc)) {
>  
> +		pm_runtime_get_sync(host->dev);
> +
>  		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
>  			min_uv = 3300000;
>  			max_uv = 3300000;
> @@ -1011,6 +1052,9 @@ static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
>  			max_uv = 1800000;
>  		} else {
>  			dev_err(host->dev, "Unsupported signal voltage!\n");
> +
> +			pm_runtime_mark_last_busy(host->dev);
> +			pm_runtime_put_autosuspend(host->dev);
>  			return -EINVAL;
>  		}
>  
> @@ -1022,6 +1066,8 @@ static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
>  		}
>  	}
>  
> +	pm_runtime_mark_last_busy(host->dev);
> +	pm_runtime_put_autosuspend(host->dev);

This is unbalanced. You do a pm_runtime_get_sync() depending on
!IS_ERR(mmc->supply.vqmmc), but you call pm_runtime_put_autosuspend()
unconditionally. Besides, I don't see that the pm_ops are necessary here
at all. This function does nothing on the controller.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr 19 23:52:29 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 20 Apr 2015 08:52:29 +0200
Subject: [PATCH v2 3/5] mmc: mediatek: Add PM support for MMC driver
In-Reply-To: <1426562035-16709-4-git-send-email-chaotian.jing@mediatek.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-4-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150420065229.GP4946@pengutronix.de>

On Tue, Mar 17, 2015 at 11:13:53AM +0800, Chaotian Jing wrote:
> Add PM support for Mediatek MMC driver
> 
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  drivers/mmc/host/mtk-sd.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 93 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 86c999b..e02f6a6 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -1186,6 +1232,8 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	int ret;
>  	u32 ddr = 0;
>  
> +	pm_runtime_get_sync(host->dev);
> +
>  	if (ios->timing == MMC_TIMING_UHS_DDR50)
>  		ddr = 1;
>  
> @@ -1230,6 +1278,9 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  
>  	if (host->mclk != ios->clock || host->ddr != ddr)
>  		msdc_set_mclk(host, ddr, ios->clock);
> +
> +	pm_runtime_mark_last_busy(host->dev);
> +	pm_runtime_put_autosuspend(host->dev);

This may also be imbalanced. This function can return between
pm_runtime_get_sync() and pm_runtime_put_autosuspend().

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 20 01:31:16 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 20 Apr 2015 10:31:16 +0200
Subject: [PATCH v2 1/5] mmc: dt-bindings: add Mediatek MMC bindings
In-Reply-To: <1426562035-16709-2-git-send-email-chaotian.jing@mediatek.com>
References: <1426562035-16709-1-git-send-email-chaotian.jing@mediatek.com>
 <1426562035-16709-2-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150420083116.GQ4946@pengutronix.de>

Hi Chaotian,

On Tue, Mar 17, 2015 at 11:13:51AM +0800, Chaotian Jing wrote:
> Document the device-tree binding of Mediatek MMC host
> 
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  Documentation/devicetree/bindings/mmc/mtk-sd.txt | 33 ++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt
> 
> diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
> new file mode 100644
> index 0000000..ac43f77
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
> @@ -0,0 +1,33 @@
> +* MTK MMC controller
> +
> +The MTK  MSDC can act as a MMC controller
> +to support MMC, SD, and SDIO types of memory cards.
> +
> +This file documents differences between the core properties in mmc.txt
> +and the properties used by the msdc driver.
> +
> +Required properties:
> +- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc".
> +- interrupts: Should contain MSDC interrupt number
> +- clocks: MSDC source clock
> +- clock-names: "source"

When I remove the clk_ignore_unused from the command line SD/MMC stops
working on the MT8173. This is because msdc50_0_h_sel is disabled, when
I enable this clock SD/MMC works again. This clock should probably be
added here and handled appropriatly in the driver.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From pi-cheng.chen at linaro.org  Mon Apr 20 02:25:50 2015
From: pi-cheng.chen at linaro.org (pi-cheng.chen)
Date: Mon, 20 Apr 2015 17:25:50 +0800
Subject: [PATCH v2] clk: mediatek: Export CPU mux clocks for CPU frequency
 control
Message-ID: <1429521950-16431-1-git-send-email-pi-cheng.chen@linaro.org>

This patch adds CPU mux clocks which are used by Mediatek cpufreq driver for
intermediate clock source switching. It is based on v11 of common clock support
for Mediatek MT8135 and MT8173[1]

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-April/335967.html

Changes in v2:
- Remove use of .determine_rate callback

Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
---
 drivers/clk/mediatek/Makefile          |   2 +-
 drivers/clk/mediatek/clk-cpumux.c      | 122 +++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-cpumux.h      |  31 +++++++++
 drivers/clk/mediatek/clk-mt8173.c      |  23 +++++++
 include/dt-bindings/clock/mt8173-clk.h |   4 +-
 5 files changed, 180 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/mediatek/clk-cpumux.c
 create mode 100644 drivers/clk/mediatek/clk-cpumux.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 8e4b2a4..299917a 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,4 @@
-obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-cpumux.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 obj-y += clk-mt8135.o
 obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
new file mode 100644
index 0000000..dc14074
--- /dev/null
+++ b/drivers/clk/mediatek/clk-cpumux.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-cpumux.h"
+
+static inline struct mtk_clk_cpumux *to_clk_mux(struct clk_hw *_hw)
+{
+	return container_of(_hw, struct mtk_clk_cpumux, hw);
+}
+
+static u8 clk_cpumux_get_parent(struct clk_hw *hw)
+{
+	struct mtk_clk_cpumux *mux = to_clk_mux(hw);
+	int num_parents = __clk_get_num_parents(hw->clk);
+	u32 val;
+
+	regmap_read(mux->regmap, mux->reg, &val);
+
+	val >>= mux->shift;
+	val &= mux->mask;
+
+	if (val >= num_parents)
+		return -EINVAL;
+
+	return val;
+}
+
+static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mtk_clk_cpumux *mux = to_clk_mux(hw);
+	u32 mask, val;
+
+	val = index << mux->shift;
+	mask = mux->mask << mux->shift;
+
+	return regmap_update_bits(mux->regmap, mux->reg, mask, val);
+}
+
+static struct clk_ops clk_cpumux_ops = {
+	.get_parent = clk_cpumux_get_parent,
+	.set_parent = clk_cpumux_set_parent,
+};
+
+static struct clk *mtk_clk_register_cpumux(const struct mtk_composite *mux,
+					   struct regmap *regmap)
+{
+	struct mtk_clk_cpumux *cpumux;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
+	if (!cpumux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = mux->name;
+	init.ops = &clk_cpumux_ops;
+	init.parent_names = mux->parent_names;
+	init.num_parents = mux->num_parents;
+
+	cpumux->reg = mux->mux_reg;
+	cpumux->shift = mux->mux_shift;
+	cpumux->mask = (BIT(mux->mux_width) - 1);
+	cpumux->regmap = regmap;
+	cpumux->hw.init = &init;
+
+	clk = clk_register(NULL, &cpumux->hw);
+	if (IS_ERR(clk))
+		kfree(cpumux);
+
+	return clk;
+}
+
+int mtk_clk_register_cpumuxes(struct device_node *node,
+			      const struct mtk_composite *clks, int num,
+			      struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	if (!clk_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+		       PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_composite *mux = &clks[i];
+
+		clk = mtk_clk_register_cpumux(mux, regmap);
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+			       mux->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[mux->id] = clk;
+	}
+
+	return 0;
+}
diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h
new file mode 100644
index 0000000..b82ad20
--- /dev/null
+++ b/drivers/clk/mediatek/clk-cpumux.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
+ *
+ * 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.
+ */
+
+#ifndef __DRV_CLK_CPUMUX_H
+#define __DRV_CLK_CPUMUX_H
+
+#include <linux/regmap.h>
+
+struct mtk_clk_cpumux {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	u32		reg;
+	u32		mask;
+	u8		shift;
+};
+
+int mtk_clk_register_cpumuxes(struct device_node *node,
+			      const struct mtk_composite *clks, int num,
+			      struct clk_onecell_data *clk_data);
+#endif /* __DRV_CLK_CPUMUX_H */
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 0584554..745f9d9 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -19,6 +19,7 @@
 
 #include "clk-mtk.h"
 #include "clk-gate.h"
+#include "clk-cpumux.h"
 
 #include <dt-bindings/clock/mt8173-clk.h>
 
@@ -517,6 +518,20 @@ static const char * const i2s3_b_ck_parents[] __initconst = {
 	"apll2_div5"
 };
 
+static const char * const ca53_parents[] __initconst = {
+	"clk26m",
+	"armca7pll",
+	"mainpll",
+	"univpll"
+};
+
+static const char * const ca57_parents[] __initconst = {
+	"clk26m",
+	"armca15pll",
+	"mainpll",
+	"univpll"
+};
+
 static const struct mtk_composite top_muxes[] __initconst = {
 	/* CLK_CFG_0 */
 	MUX(TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
@@ -589,6 +604,11 @@ static const struct mtk_composite top_muxes[] __initconst = {
 	MUX(TOP_I2S3_B_CK_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
 };
 
+static const struct mtk_composite cpu_muxes[] __initconst = {
+	MUX(INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2),
+	MUX(INFRA_CA57SEL, "infra_ca57_sel", ca57_parents, 0x0000, 2, 2),
+};
+
 static void __init mtk_init_clk_topckgen(void __iomem *top_base,
 		struct clk_onecell_data *clk_data)
 {
@@ -745,6 +765,9 @@ static void __init mtk_infrasys_init(struct device_node *node)
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 						clk_data);
 
+	mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
+						clk_data);
+
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
index e648b28..2503b03 100644
--- a/include/dt-bindings/clock/mt8173-clk.h
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -187,7 +187,9 @@
 #define INFRA_CEC		9
 #define INFRA_PMICSPI		10
 #define INFRA_PMICWRAP		11
-#define INFRA_NR_CLK		12
+#define INFRA_CA53SEL		12
+#define INFRA_CA57SEL		13
+#define INFRA_NR_CLK		14
 
 /* PERI_SYS */
 
-- 
1.9.1



From pi-cheng.chen at linaro.org  Mon Apr 20 02:27:25 2015
From: pi-cheng.chen at linaro.org (pi-cheng.chen)
Date: Mon, 20 Apr 2015 17:27:25 +0800
Subject: [PATCH v3 0/2] cpufreq: add cpufreq driver for Mediatek MT8173 SoC
Message-ID: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>

MT8173 is a ARMv8 based SoC with 2 clusters. All CPUs in a single cluster
share the same power and clock domain. This series tries to add cpufreq support
for MT8173 SoC.

Changes in v3:
- Implement MT8173 specific standalone cpufreq driver instead of using
  cpufreq-dt driver
- Define OPP table in the driver source code until new OPP binding is ready

Changes in v2:
- Add intermediate frequency support in cpufreq-dt driver
- Use voltage scaling code of cpufreq-dt for little cluster instead of
  implementaion in notifier of mtk-cpufreq driver
- Code refinement for mtk-cpufreq driver

pi-cheng.chen (2):
  cpufreq: mediatek: Add Mediatek MT8173 cpufreq driver
  ARM64: mt8173: dts: Add MT8173 cpufreq driver support

 arch/arm64/boot/dts/mediatek/mt8173-evb.dts |   9 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi    |   6 +
 drivers/cpufreq/Kconfig.arm                 |   6 +
 drivers/cpufreq/Makefile                    |   1 +
 drivers/cpufreq/mt8173-cpufreq.c            | 509 ++++++++++++++++++++++++++++
 5 files changed, 531 insertions(+)
 create mode 100644 drivers/cpufreq/mt8173-cpufreq.c

-- 
1.9.1



From pi-cheng.chen at linaro.org  Mon Apr 20 02:27:26 2015
From: pi-cheng.chen at linaro.org (pi-cheng.chen)
Date: Mon, 20 Apr 2015 17:27:26 +0800
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>

This patch implements MT8173 specific cpufreq driver with OPP table defined
in the driver code.

Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
---
 drivers/cpufreq/Kconfig.arm      |   6 +
 drivers/cpufreq/Makefile         |   1 +
 drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 516 insertions(+)
 create mode 100644 drivers/cpufreq/mt8173-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 1b06fc4..25643c7 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -132,6 +132,12 @@ config ARM_KIRKWOOD_CPUFREQ
 	  This adds the CPUFreq driver for Marvell Kirkwood
 	  SoCs.
 
+config ARM_MT8173_CPUFREQ
+	bool "Mediatek MT8173 CPUFreq support"
+	depends on ARCH_MEDIATEK && REGULATOR
+	help
+	  This adds the CPUFreq driver support for Mediatek MT8173 SoC.
+
 config ARM_OMAP2PLUS_CPUFREQ
 	bool "TI OMAP2+"
 	depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 82a1821..da9d616 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)	+= highbank-cpufreq.o
 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
 obj-$(CONFIG_ARM_INTEGRATOR)		+= integrator-cpufreq.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= kirkwood-cpufreq.o
+obj-$(CONFIG_ARM_MT8173_CPUFREQ)	+= mt8173-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
new file mode 100644
index 0000000..a310e72
--- /dev/null
+++ b/drivers/cpufreq/mt8173-cpufreq.c
@@ -0,0 +1,509 @@
+/*
+* Copyright (c) 2015 Linaro Ltd.
+* Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
+*
+* 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.
+*/
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#define MIN_VOLT_SHIFT		100000
+#define MAX_VOLT_SHIFT		200000
+
+#define OPP(f, vp, vs) {		\
+		.freq	= f,		\
+		.vproc	= vp,		\
+		.vsram	= vs,		\
+	}
+
+struct mtk_cpu_opp {
+	unsigned int freq;
+	int vproc;
+	int vsram;
+};
+
+/*
+ * The struct cpu_dvfs_info holds necessary information for doing CPU DVFS of
+ * each cluster. For Mediatek SoCs, each CPU cluster in SoC has two voltage
+ * inputs, Vproc and Vsram. For some cluster in SoC, the two voltage inputs are
+ * supplied by different PMICs. In this case, when scaling up/down the voltage
+ * of Vsram and Vproc, the two voltage inputs need to be controlled under a
+ * hardware limitation: 100mV < Vsram - Vproc < 200mV
+ * When scaling up/down the clock frequency of a cluster, the clock source need
+ * to be switched to another stable PLL clock temporarily, and switched back to
+ * the original PLL after the it becomes stable at target frequency.
+ * Hence the voltage inputs of cluster need to be set to an intermediate voltage
+ * before the clock frequency being scaled up/down.
+ */
+
+struct cpu_dvfs_info {
+	cpumask_t cpus;
+
+	struct mtk_cpu_opp *opp_tbl;
+	struct mtk_cpu_opp *intermediate_opp;
+	int nr_opp;
+
+	struct regulator *proc_reg;
+	struct regulator *sram_reg;
+	struct clk *cpu_clk;
+	struct clk *inter_pll;
+};
+
+/*
+ * This is a temporary solution until we have new OPPv2 bindings. Therefore we
+ * could describe the OPPs with (freq, volt, volt) tuple properly in device
+ * tree.
+ */
+
+/* OPP table for LITTLE cores of MT8173 */
+struct mtk_cpu_opp mt8173_l_opp[] = {
+	OPP(507000000, 859000, 0),
+	OPP(702000000, 908000, 0),
+	OPP(1001000000, 983000, 0),
+	OPP(1105000000, 1009000, 0),
+	OPP(1183000000, 1028000, 0),
+	OPP(1404000000, 1083000, 0),
+	OPP(1508000000, 1109000, 0),
+	OPP(1573000000, 1125000, 0),
+};
+
+/* OPP table for big cores of MT8173 */
+struct mtk_cpu_opp mt8173_b_opp[] = {
+	OPP(507000000, 828000, 928000),
+	OPP(702000000, 867000, 967000),
+	OPP(1001000000, 927000, 1027000),
+	OPP(1209000000, 968000, 1068000),
+	OPP(1404000000, 1007000, 1107000),
+	OPP(1612000000, 1049000, 1149000),
+	OPP(1807000000, 1089000, 1150000),
+	OPP(1989000000, 1125000, 1150000),
+};
+
+static inline int need_voltage_trace(struct cpu_dvfs_info *info)
+{
+	return (!IS_ERR_OR_NULL(info->proc_reg) &&
+		!IS_ERR_OR_NULL(info->sram_reg));
+}
+
+static struct mtk_cpu_opp *cpu_opp_find_freq_ceil(struct mtk_cpu_opp *opp_tbl,
+						  int nr_opp,
+						  unsigned long rate)
+{
+	int i;
+
+	for (i = 0; i < nr_opp; i++)
+		if (opp_tbl[i].freq >= rate)
+			return &opp_tbl[i];
+
+	return NULL;
+}
+
+/*
+ * Query the exact voltage value that is largest previous to the input voltage
+ * value supported by the regulator
+ */
+static int get_regulator_voltage_ceil(struct regulator *regulator, int voltage)
+{
+	int cnt, i, volt = -1;
+
+	if (IS_ERR_OR_NULL(regulator))
+		return -EINVAL;
+
+	cnt = regulator_count_voltages(regulator);
+	for (i = 0; i < cnt && volt < voltage; i++)
+		volt = regulator_list_voltage(regulator, i);
+
+	return (i >= cnt) ? -EINVAL : volt;
+}
+
+/*
+ * Query the exact voltage value that is smallest following to the input voltage
+ * value supported by the regulator
+ */
+static int get_regulator_voltage_floor(struct regulator *regulator, int voltage)
+{
+	int cnt, i, volt = -1;
+
+	if (IS_ERR_OR_NULL(regulator))
+		return -EINVAL;
+
+	cnt = regulator_count_voltages(regulator);
+	/* skip all trailing 0s in the list of supported voltages */
+	for (i = cnt - 1; i >= 0 && volt <= 0; i--)
+		volt = regulator_list_voltage(regulator, i);
+
+	for (; i >= 0; i--) {
+		volt = regulator_list_voltage(regulator, i);
+		if (volt <= voltage)
+			return volt;
+	}
+
+	return -EINVAL;
+}
+
+static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
+				     struct mtk_cpu_opp *opp)
+{
+	struct regulator *proc_reg = info->proc_reg;
+	struct regulator *sram_reg = info->sram_reg;
+	int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
+
+	old_vproc = regulator_get_voltage(proc_reg);
+	old_vsram = regulator_get_voltage(sram_reg);
+
+	new_vproc = opp->vproc;
+	new_vsram = opp->vsram;
+
+	/*
+	 * In the case the voltage is going to be scaled up, Vsram and Vproc
+	 * need to be scaled up step by step. In each step, Vsram needs to be
+	 * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
+	 * Repeat the step until Vsram and Vproc are set to target voltage.
+	 */
+	if (old_vproc < new_vproc) {
+next_up_step:
+		old_vsram = regulator_get_voltage(sram_reg);
+
+		vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
+			new_vsram : old_vproc + MAX_VOLT_SHIFT;
+		vsram = get_regulator_voltage_floor(sram_reg, vsram);
+
+		ret = regulator_set_voltage(sram_reg, vsram, vsram);
+		if (ret)
+			return ret;
+
+		vproc = (new_vsram == vsram) ?
+			new_vproc : vsram - MIN_VOLT_SHIFT;
+		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
+
+		ret = regulator_set_voltage(proc_reg, vproc, vproc);
+		if (ret) {
+			regulator_set_voltage(sram_reg, old_vsram, old_vsram);
+			return ret;
+		}
+
+		if (new_vproc == vproc && new_vsram == vsram)
+			return 0;
+
+		old_vproc = vproc;
+		goto next_up_step;
+
+	/*
+	 * In the case the voltage is going to be scaled down, Vsram and Vproc
+	 * need to be scaled down step by step. In each step, Vproc needs to be
+	 * set to (Vsram - 200mV) first, then Vproc is set to (Vproc + 100mV).
+	 * Repeat the step until Vsram and Vproc are set to target voltage.
+	 */
+	} else if (old_vproc > new_vproc) {
+next_down_step:
+		old_vproc = regulator_get_voltage(proc_reg);
+
+		vproc = (old_vsram - new_vproc < MAX_VOLT_SHIFT) ?
+			new_vproc : old_vsram - MAX_VOLT_SHIFT;
+		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
+
+		ret = regulator_set_voltage(proc_reg, vproc, vproc);
+		if (ret)
+			return ret;
+
+		vsram = (new_vproc == vproc) ?
+			new_vsram : vproc + MIN_VOLT_SHIFT;
+		vsram = get_regulator_voltage_floor(sram_reg, vsram);
+
+		ret = regulator_set_voltage(sram_reg, vsram, vsram);
+		if (ret) {
+			regulator_set_voltage(proc_reg, old_vproc, old_vproc);
+			return ret;
+		}
+
+		if (new_vproc == vproc && new_vsram == vsram)
+			return 0;
+
+		old_vsram = vsram;
+		goto next_down_step;
+	}
+
+	WARN_ON(1);
+	return 0;
+}
+
+static int mt8173_cpufreq_set_voltage(struct cpu_dvfs_info *info,
+				      struct mtk_cpu_opp *opp)
+{
+	if (need_voltage_trace(info))
+		return mtk_cpufreq_voltage_trace(info, opp);
+	else
+		return regulator_set_voltage(info->proc_reg, opp->vproc,
+					     opp->vproc);
+}
+
+static int mt8173_cpufreq_set_target(struct cpufreq_policy *policy,
+				     unsigned int index)
+{
+	struct cpufreq_frequency_table *freq_table = policy->freq_table;
+	struct clk *cpu_clk = policy->clk;
+	struct clk *armpll = clk_get_parent(cpu_clk);
+	struct cpu_dvfs_info *info;
+	struct mtk_cpu_opp *new_opp, *target_opp, *inter_opp, *orig_opp;
+	long freq_hz, orig_freq_hz;
+	int old_vproc, ret;
+
+	info = (struct cpu_dvfs_info *)policy->driver_data;
+	inter_opp = info->intermediate_opp;
+	orig_freq_hz = clk_get_rate(cpu_clk);
+	orig_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp,
+					  orig_freq_hz);
+	if (!orig_opp)
+		return -EINVAL;
+
+	old_vproc = regulator_get_voltage(info->proc_reg);
+	freq_hz = freq_table[index].frequency * 1000;
+	new_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp, freq_hz);
+	target_opp = new_opp;
+
+	if (!new_opp)
+		return -EINVAL;
+
+	if (target_opp->vproc < inter_opp->vproc)
+		target_opp = info->intermediate_opp;
+
+	if (old_vproc < target_opp->vproc) {
+		ret = mt8173_cpufreq_set_voltage(info, target_opp);
+		if (ret) {
+			pr_err("cpu%d: failed to scale up voltage!\n",
+			       policy->cpu);
+			mt8173_cpufreq_set_voltage(info, orig_opp);
+			return ret;
+		}
+	}
+
+	ret = clk_set_parent(cpu_clk, info->inter_pll);
+	if (ret) {
+		pr_err("cpu%d: failed to re-parent cpu clock!\n",
+		       policy->cpu);
+		mt8173_cpufreq_set_voltage(info, orig_opp);
+		WARN_ON(1);
+		return ret;
+	}
+
+	ret = clk_set_rate(armpll, freq_hz);
+	if (ret) {
+		pr_err("cpu%d: failed to scale cpu clock rate!\n",
+		       policy->cpu);
+		clk_set_parent(cpu_clk, armpll);
+		mt8173_cpufreq_set_voltage(info, orig_opp);
+		return ret;
+	}
+
+	ret = clk_set_parent(cpu_clk, armpll);
+	if (ret) {
+		pr_err("cpu%d: failed to re-parent cpu clock!\n",
+		       policy->cpu);
+		mt8173_cpufreq_set_voltage(info, inter_opp);
+		WARN_ON(1);
+		return ret;
+	}
+
+	if (new_opp->vproc < inter_opp->vproc) {
+		ret = mt8173_cpufreq_set_voltage(info, new_opp);
+		if (ret) {
+			pr_err("cpu%d: failed to scale down voltage!\n",
+			       policy->cpu);
+			clk_set_parent(cpu_clk, info->inter_pll);
+			clk_set_rate(armpll, orig_freq_hz);
+			clk_set_parent(cpu_clk, armpll);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int mt8173_cpufreq_cpu_opp_fixup(struct cpu_dvfs_info *info)
+{
+	struct mtk_cpu_opp *opp_tbl = info->opp_tbl;
+	struct regulator *proc_reg = info->proc_reg;
+	struct regulator *sram_reg = info->sram_reg;
+	int vproc, vsram, i;
+
+	for (i = 0; i < info->nr_opp; i++) {
+		vproc = opp_tbl[i].vproc;
+		vsram = opp_tbl[i].vsram;
+
+		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
+
+		if (!IS_ERR_OR_NULL(sram_reg))
+			vsram = get_regulator_voltage_ceil(sram_reg, vsram);
+
+		if (vproc < 0 || (!IS_ERR_OR_NULL(sram_reg) && vsram < 0)) {
+			pr_err("%s: Failed to get voltage setting of OPPs\n",
+			       __func__);
+			return -EINVAL;
+		}
+
+		opp_tbl[i].vproc = vproc;
+		opp_tbl[i].vsram = vsram;
+	}
+
+	return 0;
+}
+
+static int mt8173_cpufreq_dvfs_init(struct cpu_dvfs_info *info)
+{
+	struct device *cpu_dev;
+	struct regulator *proc_reg, *sram_reg;
+	struct clk *cpu_clk, *inter_pll;
+	unsigned long rate;
+	int cpu, ret;
+
+	cpu = cpumask_first(&info->cpus);
+
+try_next_cpu:
+	cpu_dev = get_cpu_device(cpu);
+	proc_reg = regulator_get_exclusive(cpu_dev, "proc");
+	sram_reg = regulator_get_exclusive(cpu_dev, "sram");
+	cpu_clk = clk_get(cpu_dev, "cpu");
+	inter_pll = clk_get(cpu_dev, "intermediate");
+
+	if (IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(cpu_clk) ||
+	    IS_ERR_OR_NULL(inter_pll)) {
+		cpu = cpumask_next(cpu, &info->cpus);
+		if (cpu >= nr_cpu_ids)
+			return -ENODEV;
+
+		goto try_next_cpu;
+	}
+
+	/* Both PROC and SRAM regulators are present. This is a big
+	 * cluster, and needs to do voltage tracing. */
+	if (!(IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(sram_reg))) {
+		info->opp_tbl = mt8173_b_opp;
+		info->nr_opp = sizeof(mt8173_b_opp) / sizeof(mt8173_b_opp[0]);
+	} else {
+		info->opp_tbl = mt8173_l_opp;
+		info->nr_opp = sizeof(mt8173_l_opp) / sizeof(mt8173_l_opp[0]);
+	}
+
+	info->proc_reg = proc_reg;
+	info->sram_reg = sram_reg;
+	info->cpu_clk = cpu_clk;
+	info->inter_pll = inter_pll;
+
+	ret = mt8173_cpufreq_cpu_opp_fixup(info);
+	if (ret) {
+		pr_err("%s: Failed to fixup opp table: %d\n", __func__, ret);
+		return ret;
+	}
+
+	rate = clk_get_rate(info->inter_pll);
+	info->intermediate_opp = cpu_opp_find_freq_ceil(info->opp_tbl,
+							info->nr_opp,
+							rate);
+	if (!info->intermediate_opp) {
+		pr_err("%s: Failed to setup intermediate opp\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void mt8173_cpufreq_dvfs_release(struct cpu_dvfs_info *info)
+{
+	regulator_put(info->proc_reg);
+	regulator_put(info->sram_reg);
+	clk_put(info->cpu_clk);
+	clk_put(info->inter_pll);
+
+	kfree(info);
+}
+
+static int mt8173_cpufreq_init(struct cpufreq_policy *policy)
+{
+	struct cpu_dvfs_info *info;
+	struct cpufreq_frequency_table *freq_table;
+	int ret, i;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	cpumask_copy(&info->cpus, &cpu_topology[policy->cpu].core_sibling);
+	ret = mt8173_cpufreq_dvfs_init(info);
+	if (ret) {
+		pr_err("%s: Failed to initialize DVFS info: %d\n", __func__,
+		       ret);
+		goto out_dvfs_release;
+	}
+
+	freq_table = kcalloc(info->nr_opp, sizeof(*freq_table), GFP_KERNEL);
+	if (!freq_table) {
+		ret = -ENOMEM;
+		goto out_dvfs_release;
+	}
+
+	for (i = 0; i < info->nr_opp; i++)
+		freq_table[i].frequency = info->opp_tbl[i].freq / 1000;
+
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	ret = cpufreq_table_validate_and_show(policy, freq_table);
+	if (ret) {
+		pr_err("%s: invalid frequency table: %d\n", __func__, ret);
+		goto out_free_freq_table;
+	}
+
+	cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling);
+	policy->driver_data = info;
+	policy->clk = info->cpu_clk;
+
+	return 0;
+
+out_free_freq_table:
+	kfree(freq_table);
+out_dvfs_release:
+	mt8173_cpufreq_dvfs_release(info);
+	return ret;
+}
+
+static int mt8173_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	kfree(&policy->freq_table);
+	policy->freq_table = NULL;
+
+	return 0;
+}
+
+static struct cpufreq_driver mt8173_cpufreq_driver = {
+	.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+	.verify = cpufreq_generic_frequency_table_verify,
+	.target_index = mt8173_cpufreq_set_target,
+	.get = cpufreq_generic_get,
+	.init = mt8173_cpufreq_init,
+	.exit = mt8173_cpufreq_exit,
+	.name = "mt8173-cpufreq",
+	.attr = cpufreq_generic_attr,
+};
+
+static int mt8173_cpufreq_driver_init(void)
+{
+	if (!of_machine_is_compatible("mediatek,mt8173"))
+		return -ENODEV;
+
+	return cpufreq_register_driver(&mt8173_cpufreq_driver);
+}
+
+module_init(mt8173_cpufreq_driver_init);
-- 
1.9.1



From pi-cheng.chen at linaro.org  Mon Apr 20 02:27:27 2015
From: pi-cheng.chen at linaro.org (pi-cheng.chen)
Date: Mon, 20 Apr 2015 17:27:27 +0800
Subject: [PATCH 2/2] ARM64: mt8173: dts Add MT8173 cpufreq driver support
In-Reply-To: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <1429522047-16675-3-git-send-email-pi-cheng.chen@linaro.org>

This patch adds voltage supplies and clocks used by MT8173 cpufreq driver.

Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
---
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 9 +++++++++
 arch/arm64/boot/dts/mediatek/mt8173.dtsi    | 6 ++++++
 2 files changed, 15 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 96e141c..7a00cfe 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -330,3 +330,12 @@
 	status = "okay";
 	clock-frequency = <100000>;
 };
+
+&cpu0 {
+	proc-supply = <&mt6397_vpca15_reg>;
+};
+
+&cpu2 {
+	proc-supply = <&da9211_vcpu_reg>;
+	sram-supply = <&mt6397_vsramca7_reg>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index d9cc84e..b8a5454 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -51,6 +51,9 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
 			reg = <0x000>;
+			clocks = <&infracfg INFRA_CA53SEL>,
+				 <&apmixedsys APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
 		};
 
 		cpu1: cpu at 1 {
@@ -65,6 +68,9 @@
 			compatible = "arm,cortex-a57";
 			reg = <0x100>;
 			enable-method = "psci";
+			clocks = <&infracfg INFRA_CA57SEL>,
+				 <&apmixedsys APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
 		};
 
 		cpu3: cpu at 101 {
-- 
1.9.1



From colin.king at canonical.com  Mon Apr 20 04:15:16 2015
From: colin.king at canonical.com (Colin King)
Date: Mon, 20 Apr 2015 06:15:16 -0500
Subject: [PATCH] pinctrl: mediatek: mtk-common: initialize unmask
Message-ID: <1429528516-9245-1-git-send-email-colin.king@canonical.com>

From: Colin Ian King <colin.king at canonical.com>

cppcheck detected an unitialized variable:

[drivers/pinctrl/mediatek/pinctrl-mtk-common.c:897]:
  (error) Uninitialized variable: unmask

unmask should be initialized to zero to ensure unmasking
only occurs if a previous mask occurred. The current situation
is that the unmask variable could contain any random garbage
causing random unexpected unmasking.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 493294c..3173125 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -881,7 +881,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
 	if (!mtk_eint_get_mask(pctl, eint_num)) {
 		mtk_eint_mask(d);
 		unmask = 1;
-	}
+	} else
+		unmask = 0;
 
 	clr_bit = 0xff << eint_offset;
 	writel(clr_bit, pctl->eint_reg_base + clr_offset);
-- 
2.1.4



From sergei.shtylyov at cogentembedded.com  Mon Apr 20 05:32:51 2015
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Mon, 20 Apr 2015 15:32:51 +0300
Subject: [PATCH] pinctrl: mediatek: mtk-common: initialize unmask
In-Reply-To: <1429528516-9245-1-git-send-email-colin.king@canonical.com>
References: <1429528516-9245-1-git-send-email-colin.king@canonical.com>
Message-ID: <5534F1F3.9060802@cogentembedded.com>

Hello.

On 04/20/2015 02:15 PM, Colin King wrote:

> From: Colin Ian King <colin.king at canonical.com>

> cppcheck detected an unitialized variable:

    Uninitialized.

> [drivers/pinctrl/mediatek/pinctrl-mtk-common.c:897]:
>    (error) Uninitialized variable: unmask

> unmask should be initialized to zero to ensure unmasking
> only occurs if a previous mask occurred. The current situation
> is that the unmask variable could contain any random garbage
> causing random unexpected unmasking.

> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>   drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)

> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> index 493294c..3173125 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> @@ -881,7 +881,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
>   	if (!mtk_eint_get_mask(pctl, eint_num)) {
>   		mtk_eint_mask(d);
>   		unmask = 1;
> -	}
> +	} else
> +		unmask = 0;

    The CodingStyle dictates that there should be {} around *else* branch too.

[...]

WBR, Sergei



From joshc at ni.com  Mon Apr 20 07:17:19 2015
From: joshc at ni.com (Josh Cartwright)
Date: Mon, 20 Apr 2015 09:17:19 -0500
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>

On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
> This patch implements MT8173 specific cpufreq driver with OPP table defined
> in the driver code.
> 
> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
> ---
>  drivers/cpufreq/Kconfig.arm      |   6 +
>  drivers/cpufreq/Makefile         |   1 +
>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 516 insertions(+)
>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 1b06fc4..25643c7 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -132,6 +132,12 @@ config ARM_KIRKWOOD_CPUFREQ
>  	  This adds the CPUFreq driver for Marvell Kirkwood
>  	  SoCs.
>  
> +config ARM_MT8173_CPUFREQ
> +	bool "Mediatek MT8173 CPUFreq support"
> +	depends on ARCH_MEDIATEK && REGULATOR

I think you want to 'select REGULATOR' here; because REGULATOR isn't
a user-visible option.

> +	help
> +	  This adds the CPUFreq driver support for Mediatek MT8173 SoC.
> +
>  config ARM_OMAP2PLUS_CPUFREQ
>  	bool "TI OMAP2+"
>  	depends on ARCH_OMAP2PLUS
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 82a1821..da9d616 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)	+= highbank-cpufreq.o
>  obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
>  obj-$(CONFIG_ARM_INTEGRATOR)		+= integrator-cpufreq.o
>  obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= kirkwood-cpufreq.o
> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)	+= mt8173-cpufreq.o
>  obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
>  obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
>  obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
> diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
> new file mode 100644
> index 0000000..a310e72
> --- /dev/null
> +++ b/drivers/cpufreq/mt8173-cpufreq.c
> @@ -0,0 +1,509 @@
> +/*
> +* Copyright (c) 2015 Linaro Ltd.
> +* Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
> +*
> +* 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.
> +*/
> +
> +#include <linux/clk.h>
> +#include <linux/cpu.h>
> +#include <linux/cpufreq.h>
> +#include <linux/cpumask.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +
> +#define MIN_VOLT_SHIFT		100000
> +#define MAX_VOLT_SHIFT		200000
> +
> +#define OPP(f, vp, vs) {		\
> +		.freq	= f,		\
> +		.vproc	= vp,		\
> +		.vsram	= vs,		\
> +	}
> +
> +struct mtk_cpu_opp {
> +	unsigned int freq;
> +	int vproc;
> +	int vsram;
> +};
> +
> +/*
> + * The struct cpu_dvfs_info holds necessary information for doing CPU DVFS of
> + * each cluster. For Mediatek SoCs, each CPU cluster in SoC has two voltage
> + * inputs, Vproc and Vsram. For some cluster in SoC, the two voltage inputs are
> + * supplied by different PMICs. In this case, when scaling up/down the voltage
> + * of Vsram and Vproc, the two voltage inputs need to be controlled under a
> + * hardware limitation: 100mV < Vsram - Vproc < 200mV
> + * When scaling up/down the clock frequency of a cluster, the clock source need
> + * to be switched to another stable PLL clock temporarily, and switched back to
> + * the original PLL after the it becomes stable at target frequency.
> + * Hence the voltage inputs of cluster need to be set to an intermediate voltage
> + * before the clock frequency being scaled up/down.
> + */
> +
> +struct cpu_dvfs_info {
> +	cpumask_t cpus;
> +
> +	struct mtk_cpu_opp *opp_tbl;
> +	struct mtk_cpu_opp *intermediate_opp;
> +	int nr_opp;
> +
> +	struct regulator *proc_reg;
> +	struct regulator *sram_reg;
> +	struct clk *cpu_clk;
> +	struct clk *inter_pll;
> +};
> +
> +/*
> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
> + * tree.
> + */
> +
> +/* OPP table for LITTLE cores of MT8173 */
> +struct mtk_cpu_opp mt8173_l_opp[] = {

static const?

> +	OPP(507000000, 859000, 0),
> +	OPP(702000000, 908000, 0),
> +	OPP(1001000000, 983000, 0),
> +	OPP(1105000000, 1009000, 0),
> +	OPP(1183000000, 1028000, 0),
> +	OPP(1404000000, 1083000, 0),
> +	OPP(1508000000, 1109000, 0),
> +	OPP(1573000000, 1125000, 0),
> +};
> +
> +/* OPP table for big cores of MT8173 */
> +struct mtk_cpu_opp mt8173_b_opp[] = {

same here?

> +	OPP(507000000, 828000, 928000),
> +	OPP(702000000, 867000, 967000),
> +	OPP(1001000000, 927000, 1027000),
> +	OPP(1209000000, 968000, 1068000),
> +	OPP(1404000000, 1007000, 1107000),
> +	OPP(1612000000, 1049000, 1149000),
> +	OPP(1807000000, 1089000, 1150000),
> +	OPP(1989000000, 1125000, 1150000),
> +};
> +
[..]
> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
> +				     struct mtk_cpu_opp *opp)
> +{
> +	struct regulator *proc_reg = info->proc_reg;
> +	struct regulator *sram_reg = info->sram_reg;
> +	int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
> +
> +	old_vproc = regulator_get_voltage(proc_reg);
> +	old_vsram = regulator_get_voltage(sram_reg);
> +
> +	new_vproc = opp->vproc;
> +	new_vsram = opp->vsram;
> +
> +	/*
> +	 * In the case the voltage is going to be scaled up, Vsram and Vproc
> +	 * need to be scaled up step by step. In each step, Vsram needs to be
> +	 * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
> +	 * Repeat the step until Vsram and Vproc are set to target voltage.
> +	 */
> +	if (old_vproc < new_vproc) {
> +next_up_step:
> +		old_vsram = regulator_get_voltage(sram_reg);
> +
> +		vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
> +			new_vsram : old_vproc + MAX_VOLT_SHIFT;
> +		vsram = get_regulator_voltage_floor(sram_reg, vsram);
> +
> +		ret = regulator_set_voltage(sram_reg, vsram, vsram);
> +		if (ret)
> +			return ret;
> +
> +		vproc = (new_vsram == vsram) ?
> +			new_vproc : vsram - MIN_VOLT_SHIFT;
> +		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
> +
> +		ret = regulator_set_voltage(proc_reg, vproc, vproc);
> +		if (ret) {
> +			regulator_set_voltage(sram_reg, old_vsram, old_vsram);
> +			return ret;
> +		}
> +
> +		if (new_vproc == vproc && new_vsram == vsram)
> +			return 0;
> +
> +		old_vproc = vproc;
> +		goto next_up_step;

Perhaps a naive question: but, is this the correct place to do this?  I
would expect this stepping behavior to be implemented in the driver
controlling the regulator you are consuming.  It seems strange to do it
here.

  Josh


From colin.king at canonical.com  Mon Apr 20 08:59:17 2015
From: colin.king at canonical.com (Colin King)
Date: Mon, 20 Apr 2015 10:59:17 -0500
Subject: [PATCH][V2] pinctrl: mediatek: mtk-common: initialize unmask
Message-ID: <1429545557-3404-1-git-send-email-colin.king@canonical.com>

From: Colin Ian King <colin.king at canonical.com>

cppcheck detected an uninitialized variable:

[drivers/pinctrl/mediatek/pinctrl-mtk-common.c:897]:
  (error) Uninitialized variable: unmask

unmask should be initialized to zero to ensure unmasking
only occurs if a previous mask occurred. The current situation
is that the unmask variable could contain any random garbage
causing random unexpected unmasking.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 493294c..474812e 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -881,6 +881,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
 	if (!mtk_eint_get_mask(pctl, eint_num)) {
 		mtk_eint_mask(d);
 		unmask = 1;
+	} else {
+		unmask = 0;
 	}
 
 	clr_bit = 0xff << eint_offset;
-- 
2.1.4



From pebolle at tiscali.nl  Mon Apr 20 11:28:37 2015
From: pebolle at tiscali.nl (Paul Bolle)
Date: Mon, 20 Apr 2015 20:28:37 +0200
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <1429554517.14597.38.camel@x220>

On Mon, 2015-04-20 at 17:27 +0800, pi-cheng.chen wrote:
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
 
> +config ARM_MT8173_CPUFREQ
> +	bool "Mediatek MT8173 CPUFreq support"
> +	depends on ARCH_MEDIATEK && REGULATOR
> +	help
> +	  This adds the CPUFreq driver support for Mediatek MT8173 SoC.

> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile

> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)	+= mt8173-cpufreq.o

ARM_MT8173_CPUFREQ is a bool symbol, so mt8173-cpufreq.o will never be
part of a module.

(If that's incorrect you can stop reading here.)

> --- /dev/null
> +++ b/drivers/cpufreq/mt8173-cpufreq.c

> +#include <linux/module.h>

I guess this include is not needed. And, for what it's worth,
    make ARCH=arm CROSS_COMPILE=arm-linux-gnu- drivers/cpufreq/mt8173-cpufreq.o

compiles silently even if it's dropped.

> +module_init(mt8173_cpufreq_driver_init);

According to include/linux/init.h, for built-in only code, this is
equivalent to device_initcall([...]). And two runs of
    make ARCH=arm CROSS_COMPILE=arm-linux-gnu- drivers/cpufreq/mt8173-cpufreq.i

confirm that.

Thanks,


Paul Bolle



From pebolle at tiscali.nl  Mon Apr 20 11:31:50 2015
From: pebolle at tiscali.nl (Paul Bolle)
Date: Mon, 20 Apr 2015 20:31:50 +0200
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>
Message-ID: <1429554710.14597.41.camel@x220>

On Mon, 2015-04-20 at 09:17 -0500, Josh Cartwright wrote:
> On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
> > --- a/drivers/cpufreq/Kconfig.arm
> > +++ b/drivers/cpufreq/Kconfig.arm
>   
> > +config ARM_MT8173_CPUFREQ
> > +	bool "Mediatek MT8173 CPUFreq support"
> > +	depends on ARCH_MEDIATEK && REGULATOR
> 
> I think you want to 'select REGULATOR' here; because REGULATOR isn't
> a user-visible option.

REGULATOR is user visible, at least in next-20150420.

> > +	help
> > +	  This adds the CPUFreq driver support for Mediatek MT8173 SoC.

Thanks,


Paul Bolle



From broonie at kernel.org  Mon Apr 20 13:48:49 2015
From: broonie at kernel.org (Mark Brown)
Date: Mon, 20 Apr 2015 21:48:49 +0100
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150420043747.GH6325@pengutronix.de>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
Message-ID: <20150420204849.GJ14892@sirena.org.uk>

On Mon, Apr 20, 2015 at 06:37:47AM +0200, Sascha Hauer wrote:
> On Sat, Apr 18, 2015 at 06:34:07PM +0100, Mark Brown wrote:
> > On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:

> > > +Each external interface (called "IO" in this driver) is presented as a
> > > +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> > > +The connection paths are configured through the device tree.

> > Why are these connection paths configured via device tree?  I would
> > expect that either there would be runtime configurability of these
> > things (particularly if loopback configurations within the hardware are
> > possible) or we'd just allocate memory interfaces to DAIs automatically
> > as DAIs come into use.

> There is a crossbar switch between the memory interfaces and the DAIs.
> Not every connection is possible, so not every memory interface can be
> used for every DAI. An algorithm choosing a suitable memory interface
> must be quite clever, complicated and also SoC dependent (the same but
> different hardware is used on MT8135 aswell), so I thought offering a
> static configuration via device tree is a good start. Should there be
> runtime configuration possible later the device tree settings could
> provide a good default.

What exactly do the restrictions look like and how often do they vary in
practice (can we get away with just doing a single static setup in the
driver)?  I'd have thought it should be fairly straightforward to have a
table of valid mappings and just pick the first free memory interface?
I'd rather not get stuck with the tables in the DT.  It's partly to
avoid setting bad precendents, we really don't want everyone coming
along hard coding this stuff, and partly because the hardware you
described didn't seem that hard to handle.

> > > +- mem-interface-playback:
> > > +  mem-interface-capture: property of memif, format is: <memif irq use_sram>;
> > > +	                 memif: which memif to be used
> > > +			        (defined in include/dt-bindings/sound/mtk-afe.h)
> > > +		         irq: which irq to be used
> > > +			      (defined in include/dt-bindings/sound/mtk-afe.h)
> > > +		         use_sram: 1 is yes, 0 is no

> > Again, this looks like stuff we should be able to figure out at runtime
> > - the use of SRAM in particular looks like something we might want to
> > change depending on use case.  Assuming it adds buffering then for a
> > VoIP application we might not want to use SRAM to minimize latency but
> > during music playback we might want to enable SRAM to minimize power
> > consumption.

> That's exactly the usecase. How could such a runtime configurability
> look like? sysfs? Or something based on the buffer sizes?

Yeah, one of those :) but probably an ALSA control is going to be the
easiest for applications.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150420/c4e99187/attachment.sig>

From broonie at kernel.org  Mon Apr 20 13:52:30 2015
From: broonie at kernel.org (Mark Brown)
Date: Mon, 20 Apr 2015 21:52:30 +0100
Subject: [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control
In-Reply-To: <20150420045017.GI6325@pengutronix.de>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
 <20150418173740.GF26185@sirena.org.uk>
 <20150420045017.GI6325@pengutronix.de>
Message-ID: <20150420205230.GK14892@sirena.org.uk>

On Mon, Apr 20, 2015 at 06:50:17AM +0200, Sascha Hauer wrote:
> On Sat, Apr 18, 2015 at 06:37:40PM +0100, Mark Brown wrote:
> > On Fri, Apr 10, 2015 at 04:14:08PM +0800, Koro Chen wrote:

> > > +	[0][0] =   { .creg = 0x020, .cshift =  0, .sreg = 0x020, .sshift = 10},
> > > +	[0][1] =   { .creg = 0x020, .cshift = 16, .sreg = 0x020, .sshift = 26},

> > It'd also be nice to have less magic numbers in the table, at least for
> > the indexes (which I guess correspond to some of the defines in the
> > headers)?

> With defines the above two lines would become something like:

> [0][0] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O00_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O00_R },
> [0][1] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O01_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O01_S },

> For the registers we could use defines, but I think using defines for
> the shifts doesn't add much value given they are only used once.

By indexes I actually meant the [0][0] and so on - they seem the more
magic bit.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150420/5bcf6617/attachment.sig>

From broonie at kernel.org  Mon Apr 20 13:55:11 2015
From: broonie at kernel.org (Mark Brown)
Date: Mon, 20 Apr 2015 21:55:11 +0100
Subject: [RESEND RFC PATCH 3/3] ASoC: mediatek: Add AFE platform driver
In-Reply-To: <1429510944.30743.36.camel@mtksdaap41>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
 <20150418175139.GG26185@sirena.org.uk>
 <1429510944.30743.36.camel@mtksdaap41>
Message-ID: <20150420205511.GL14892@sirena.org.uk>

On Mon, Apr 20, 2015 at 02:22:24PM +0800, Koro Chen wrote:
> On Sat, 2015-04-18 at 18:51 +0100, Mark Brown wrote:
> > On Fri, Apr 10, 2015 at 04:14:09PM +0800, Koro Chen wrote:

> > Ah, so the SRAM is directly memory mappable.  Nice.  But we have a
> > limited amount of it so need to allocate it to a device somehow based on
> > some factor I guess?

> Yes, actually SRAM is only used for the main playback path (which is
> memif "DL1") to achieve low power in real use case. Maybe you think it's
> better to not describe this in the device tree, but to choose SRAM
> automatically if memif "DL1" is chosen?

Since it's directly memory mappable is there actually any cost in
latency terms from using the SRAM in low latency cases (or did I misread
what the code was doing there)?  If it can only be used with one
interface and there's no downside from using it...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150420/071b0bdc/attachment.sig>

From koro.chen at mediatek.com  Mon Apr 20 19:27:13 2015
From: koro.chen at mediatek.com (Koro Chen)
Date: Tue, 21 Apr 2015 10:27:13 +0800
Subject: [RESEND RFC PATCH 3/3] ASoC: mediatek: Add AFE platform driver
In-Reply-To: <20150420205511.GL14892@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
 <20150418175139.GG26185@sirena.org.uk>
 <1429510944.30743.36.camel@mtksdaap41>
 <20150420205511.GL14892@sirena.org.uk>
Message-ID: <1429583233.14794.40.camel@mtksdaap41>

On Mon, 2015-04-20 at 21:55 +0100, Mark Brown wrote:
> On Mon, Apr 20, 2015 at 02:22:24PM +0800, Koro Chen wrote:
> > On Sat, 2015-04-18 at 18:51 +0100, Mark Brown wrote:
> > > On Fri, Apr 10, 2015 at 04:14:09PM +0800, Koro Chen wrote:
> 
> > > Ah, so the SRAM is directly memory mappable.  Nice.  But we have a
> > > limited amount of it so need to allocate it to a device somehow based on
> > > some factor I guess?
> 
> > Yes, actually SRAM is only used for the main playback path (which is
> > memif "DL1") to achieve low power in real use case. Maybe you think it's
> > better to not describe this in the device tree, but to choose SRAM
> > automatically if memif "DL1" is chosen?
> 
> Since it's directly memory mappable is there actually any cost in
> latency terms from using the SRAM in low latency cases (or did I misread
> what the code was doing there)?  If it can only be used with one
> interface and there's no downside from using it...
The SRAM size to be used is defined by params_buffer_bytes(params), not
fixed (of course limited by the actual available SRAM size on HW), so
the latency should be the same compared to a DRAM having the same size. 

The SRAM can be used by any memif, and that's why the plan was let DT
make the decision.




From s.hauer at pengutronix.de  Mon Apr 20 22:50:41 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 21 Apr 2015 07:50:41 +0200
Subject: [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control
In-Reply-To: <20150420205230.GK14892@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
 <20150418173740.GF26185@sirena.org.uk>
 <20150420045017.GI6325@pengutronix.de>
 <20150420205230.GK14892@sirena.org.uk>
Message-ID: <20150421055041.GQ6325@pengutronix.de>

On Mon, Apr 20, 2015 at 09:52:30PM +0100, Mark Brown wrote:
> On Mon, Apr 20, 2015 at 06:50:17AM +0200, Sascha Hauer wrote:
> > On Sat, Apr 18, 2015 at 06:37:40PM +0100, Mark Brown wrote:
> > > On Fri, Apr 10, 2015 at 04:14:08PM +0800, Koro Chen wrote:
> 
> > > > +	[0][0] =   { .creg = 0x020, .cshift =  0, .sreg = 0x020, .sshift = 10},
> > > > +	[0][1] =   { .creg = 0x020, .cshift = 16, .sreg = 0x020, .sshift = 26},
> 
> > > It'd also be nice to have less magic numbers in the table, at least for
> > > the indexes (which I guess correspond to some of the defines in the
> > > headers)?
> 
> > With defines the above two lines would become something like:
> 
> > [0][0] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O00_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O00_R },
> > [0][1] = { .creg = AFE_CONN0, .cshift = CONN0_I00_O01_S, .sreg = AFE_CONN0, .sshift = CONN0_I00_O01_S },
> 
> > For the registers we could use defines, but I think using defines for
> > the shifts doesn't add much value given they are only used once.
> 
> By indexes I actually meant the [0][0] and so on - they seem the more
> magic bit.

Oh, that's not magic at all, the crossbar switch has inputs and outputs
numbered from 0 to MTK_AFE_INTERCONN_NUM_INPUT /
MTK_AFE_INTERCONN_NUM_OUTPUT (they have the same numbers in the
datasheet. To connect input x with output y look at index [x][y] in the
table and write the register values found at that place. If .creg is 0x0
then it's not possible to connect the given input with the given output.

Sascha



-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 21 02:49:26 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 21 Apr 2015 11:49:26 +0200
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150420204849.GJ14892@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
Message-ID: <20150421094926.GU6325@pengutronix.de>

On Mon, Apr 20, 2015 at 09:48:49PM +0100, Mark Brown wrote:
> On Mon, Apr 20, 2015 at 06:37:47AM +0200, Sascha Hauer wrote:
> > On Sat, Apr 18, 2015 at 06:34:07PM +0100, Mark Brown wrote:
> > > On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:
> 
> > > > +Each external interface (called "IO" in this driver) is presented as a
> > > > +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> > > > +The connection paths are configured through the device tree.
> 
> > > Why are these connection paths configured via device tree?  I would
> > > expect that either there would be runtime configurability of these
> > > things (particularly if loopback configurations within the hardware are
> > > possible) or we'd just allocate memory interfaces to DAIs automatically
> > > as DAIs come into use.
> 
> > There is a crossbar switch between the memory interfaces and the DAIs.
> > Not every connection is possible, so not every memory interface can be
> > used for every DAI. An algorithm choosing a suitable memory interface
> > must be quite clever, complicated and also SoC dependent (the same but
> > different hardware is used on MT8135 aswell), so I thought offering a
> > static configuration via device tree is a good start. Should there be
> > runtime configuration possible later the device tree settings could
> > provide a good default.
> 
> What exactly do the restrictions look like and how often do they vary in
> practice (can we get away with just doing a single static setup in the
> driver)? I'd have thought it should be fairly straightforward to have a
> table of valid mappings and just pick the first free memory interface?

I think this could be done. I checked the possible connections in the
crossbar switch and it seems all memory interfaces can be connected with
all relevant external interfaces. So indeed the memory interfaces could
be dynamically allocated instead of statically associated to an
external interface. There are two problems I see: Some memory interfaces
are limited in the rates they support, they can only do 8k/16k/32k (for
speech). How can we know such memory interface should be used? Also
there are two programmable hardware gain blocks which can be inserted to
the digital audio path using the crossbar switch. There must be some
mechanism to configure them into different places.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From broonie at kernel.org  Tue Apr 21 03:05:15 2015
From: broonie at kernel.org (Mark Brown)
Date: Tue, 21 Apr 2015 11:05:15 +0100
Subject: [RESEND RFC PATCH 3/3] ASoC: mediatek: Add AFE platform driver
In-Reply-To: <1429583233.14794.40.camel@mtksdaap41>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-4-git-send-email-koro.chen@mediatek.com>
 <20150418175139.GG26185@sirena.org.uk>
 <1429510944.30743.36.camel@mtksdaap41>
 <20150420205511.GL14892@sirena.org.uk>
 <1429583233.14794.40.camel@mtksdaap41>
Message-ID: <20150421100515.GB22845@sirena.org.uk>

On Tue, Apr 21, 2015 at 10:27:13AM +0800, Koro Chen wrote:

> The SRAM size to be used is defined by params_buffer_bytes(params), not
> fixed (of course limited by the actual available SRAM size on HW), so
> the latency should be the same compared to a DRAM having the same size. 

Right, some systems have the SRAM as essentially a big FIFO but this
doesn't have that problem.

> The SRAM can be used by any memif, and that's why the plan was let DT
> make the decision.

OK, if it's for any interface rather than just DL1 like Sascha said then
it does need to be selectable, but DT doesn't seem the platce to do it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150421/9f438000/attachment.sig>

From broonie at kernel.org  Tue Apr 21 03:14:16 2015
From: broonie at kernel.org (Mark Brown)
Date: Tue, 21 Apr 2015 11:14:16 +0100
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150421094926.GU6325@pengutronix.de>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
 <20150421094926.GU6325@pengutronix.de>
Message-ID: <20150421101416.GC22845@sirena.org.uk>

On Tue, Apr 21, 2015 at 11:49:26AM +0200, Sascha Hauer wrote:

> I think this could be done. I checked the possible connections in the
> crossbar switch and it seems all memory interfaces can be connected with
> all relevant external interfaces. So indeed the memory interfaces could
> be dynamically allocated instead of statically associated to an
> external interface. There are two problems I see: Some memory interfaces
> are limited in the rates they support, they can only do 8k/16k/32k (for
> speech). How can we know such memory interface should be used? Also
> there are two programmable hardware gain blocks which can be inserted to
> the digital audio path using the crossbar switch. There must be some
> mechanism to configure them into different places.

This (particularly the gain controls) sounds like you want to expose the
routing to userspace and use DPCM, the code also seemed to look like it
was a good fit for DPCM.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150421/e006ea93/attachment.sig>

From koro.chen at mediatek.com  Tue Apr 21 03:15:06 2015
From: koro.chen at mediatek.com (Koro Chen)
Date: Tue, 21 Apr 2015 18:15:06 +0800
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150421094926.GU6325@pengutronix.de>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
 <20150421094926.GU6325@pengutronix.de>
Message-ID: <1429611306.23823.52.camel@mtksdaap41>

On Tue, 2015-04-21 at 11:49 +0200, Sascha Hauer wrote:
> On Mon, Apr 20, 2015 at 09:48:49PM +0100, Mark Brown wrote:
> > On Mon, Apr 20, 2015 at 06:37:47AM +0200, Sascha Hauer wrote:
> > > On Sat, Apr 18, 2015 at 06:34:07PM +0100, Mark Brown wrote:
> > > > On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:
> > 
> > > > > +Each external interface (called "IO" in this driver) is presented as a
> > > > > +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> > > > > +The connection paths are configured through the device tree.
> > 
> > > > Why are these connection paths configured via device tree?  I would
> > > > expect that either there would be runtime configurability of these
> > > > things (particularly if loopback configurations within the hardware are
> > > > possible) or we'd just allocate memory interfaces to DAIs automatically
> > > > as DAIs come into use.
> > 
> > > There is a crossbar switch between the memory interfaces and the DAIs.
> > > Not every connection is possible, so not every memory interface can be
> > > used for every DAI. An algorithm choosing a suitable memory interface
> > > must be quite clever, complicated and also SoC dependent (the same but
> > > different hardware is used on MT8135 aswell), so I thought offering a
> > > static configuration via device tree is a good start. Should there be
> > > runtime configuration possible later the device tree settings could
> > > provide a good default.
> > 
> > What exactly do the restrictions look like and how often do they vary in
> > practice (can we get away with just doing a single static setup in the
> > driver)? I'd have thought it should be fairly straightforward to have a
> > table of valid mappings and just pick the first free memory interface?
> 
> I think this could be done. I checked the possible connections in the
> crossbar switch and it seems all memory interfaces can be connected with
> all relevant external interfaces. So indeed the memory interfaces could
> be dynamically allocated instead of statically associated to an
> external interface. There are two problems I see: Some memory interfaces
> are limited in the rates they support, they can only do 8k/16k/32k (for
> speech). How can we know such memory interface should be used? Also
The 2 memif are "DAI" and "MOD_DAI", designed for speech cases, and they
should be only connected to corresponding external interface "DAI/BT"
and "modem", respectively. We don't need to put them into dynamic
allocation. 
> there are two programmable hardware gain blocks which can be inserted to
> the digital audio path using the crossbar switch. There must be some
> mechanism to configure them into different places.
Maybe in DPCM, they can be "widgets", and we can define "routes" and
corresponding controls for them. 
> 
> Sascha
> 




From broonie at kernel.org  Tue Apr 21 03:15:03 2015
From: broonie at kernel.org (Mark Brown)
Date: Tue, 21 Apr 2015 11:15:03 +0100
Subject: [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control
In-Reply-To: <20150421055041.GQ6325@pengutronix.de>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-3-git-send-email-koro.chen@mediatek.com>
 <20150418173740.GF26185@sirena.org.uk>
 <20150420045017.GI6325@pengutronix.de>
 <20150420205230.GK14892@sirena.org.uk>
 <20150421055041.GQ6325@pengutronix.de>
Message-ID: <20150421101503.GD22845@sirena.org.uk>

On Tue, Apr 21, 2015 at 07:50:41AM +0200, Sascha Hauer wrote:

> Oh, that's not magic at all, the crossbar switch has inputs and outputs
> numbered from 0 to MTK_AFE_INTERCONN_NUM_INPUT /
> MTK_AFE_INTERCONN_NUM_OUTPUT (they have the same numbers in the
> datasheet. To connect input x with output y look at index [x][y] in the
> table and write the register values found at that place. If .creg is 0x0
> then it's not possible to connect the given input with the given output.

A comment saying that would help then.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150421/563f9fc2/attachment.sig>

From broonie at kernel.org  Tue Apr 21 03:56:23 2015
From: broonie at kernel.org (Mark Brown)
Date: Tue, 21 Apr 2015 11:56:23 +0100
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <1429611306.23823.52.camel@mtksdaap41>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
 <20150421094926.GU6325@pengutronix.de>
 <1429611306.23823.52.camel@mtksdaap41>
Message-ID: <20150421105623.GG22845@sirena.org.uk>

On Tue, Apr 21, 2015 at 06:15:06PM +0800, Koro Chen wrote:
> On Tue, 2015-04-21 at 11:49 +0200, Sascha Hauer wrote:

> > there are two programmable hardware gain blocks which can be inserted to
> > the digital audio path using the crossbar switch. There must be some
> > mechanism to configure them into different places.

> Maybe in DPCM, they can be "widgets", and we can define "routes" and
> corresponding controls for them. 

Yes, exactly - it's basically just like a CODEC.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150421/8bf8f506/attachment.sig>

From matthias.bgg at gmail.com  Tue Apr 21 04:43:19 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 21 Apr 2015 13:43:19 +0200
Subject: Question about checking rate_spi in pwrap_init_reg_clock
In-Reply-To: <20150421103155.GX6325@pengutronix.de>
References: <1429581487.5994.1.camel@ingics.com>
 <20150421103155.GX6325@pengutronix.de>
Message-ID: <CABuKBeJqgWHWNYaFXS-BwEayHEtiYGt+56LLXs3QaO3MHUk0bQ@mail.gmail.com>

2015-04-21 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Tue, Apr 21, 2015 at 09:58:07AM +0800, Axel Lin wrote:
>> hi,
>> The implementation in pwrap_init_reg_clock seems has off-by-one bug.
>> If rate_spi is 26000000, current code set ck_mhz to 18 rather than 26.
>>
>> I guess it needs below fix, but I'm not 100% sure as I don't have the datasheet.
>> Can someone confirm if this is a bug or not?
>
> Yes, seems to be a bug. Thanks for noting. Will you send a formal patch
> or should I do it?

Did you have a look on both datasheets/reference kernels, mt8135 and mt8173?
Reading the datasheet and reference kernel code for mt6589 this SPI
waveform configuration looks like magic.

But reading the clock frequency which can have clk_spi in mt8135, they
are 0 MHz, 26 MHz and bigger then 26 MHz, which leads me to the
conclusion that the code is correct. Otherwise the check for bigger
then 18 MHz is useless and should be deleted, if we have a similar
clock distribution in mt8173.

So maybe someone from Mediatek can shed light on this issue.

Thanks,
Matthias


From matthias.bgg at gmail.com  Tue Apr 21 04:46:51 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 21 Apr 2015 13:46:51 +0200
Subject: [PATCH] soc: mediatek: Fix off-by-one checking for rate_spi
In-Reply-To: <20150421105953.GY6325@pengutronix.de>
References: <1429613612.5644.1.camel@ingics.com>
 <20150421105953.GY6325@pengutronix.de>
Message-ID: <CABuKBeL+YTZz4jkMwozm4SbtP_4N8kBiqgeEHh1htoK6StpK_w@mail.gmail.com>

Hi Sascha,

2015-04-21 12:59 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Tue, Apr 21, 2015 at 06:53:32PM +0800, Axel Lin wrote:
>> If rate_spi is 26000000, current code set ck_mhz to 18 rather than 26.
>> Fix the off-by-one checking for rate_spi.
>>
>> Signed-off-by: Axel Lin <axel.lin at ingics.com>
>
> Acked-by: Sascha Hauer <s.hauer at pengutronix.de>
>

Can you please explain why you think this is a bug? Please see my
concerns here [1].

Best regards,
Matthias

[1] http://lists.infradead.org/pipermail/linux-mediatek/2015-April/000419.html


From s.hauer at pengutronix.de  Tue Apr 21 05:52:23 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 21 Apr 2015 14:52:23 +0200
Subject: Question about checking rate_spi in pwrap_init_reg_clock
In-Reply-To: <CABuKBeJqgWHWNYaFXS-BwEayHEtiYGt+56LLXs3QaO3MHUk0bQ@mail.gmail.com>
References: <1429581487.5994.1.camel@ingics.com>
 <20150421103155.GX6325@pengutronix.de>
 <CABuKBeJqgWHWNYaFXS-BwEayHEtiYGt+56LLXs3QaO3MHUk0bQ@mail.gmail.com>
Message-ID: <20150421125223.GB6325@pengutronix.de>

On Tue, Apr 21, 2015 at 01:43:19PM +0200, Matthias Brugger wrote:
> 2015-04-21 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> > On Tue, Apr 21, 2015 at 09:58:07AM +0800, Axel Lin wrote:
> >> hi,
> >> The implementation in pwrap_init_reg_clock seems has off-by-one bug.
> >> If rate_spi is 26000000, current code set ck_mhz to 18 rather than 26.
> >>
> >> I guess it needs below fix, but I'm not 100% sure as I don't have the datasheet.
> >> Can someone confirm if this is a bug or not?
> >
> > Yes, seems to be a bug. Thanks for noting. Will you send a formal patch
> > or should I do it?
> 
> Did you have a look on both datasheets/reference kernels, mt8135 and mt8173?
> Reading the datasheet and reference kernel code for mt6589 this SPI
> waveform configuration looks like magic.
> 
> But reading the clock frequency which can have clk_spi in mt8135, they
> are 0 MHz, 26 MHz and bigger then 26 MHz, which leads me to the
> conclusion that the code is correct. Otherwise the check for bigger
> then 18 MHz is useless and should be deleted, if we have a similar
> clock distribution in mt8173.

The CSHEXT and CSLEXT registers extend the time the chipselect stays
high after a SPI transfer or low before a new transfer by the given
number of spi clk cycles.
Looking at the code maybe the real question is not whether the border is
at 25999999Hz or at 26000000Hz, but why the transfers are throttled with
slower clock frequencies. I would assume the other way round makes
sense.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Tue Apr 21 08:42:53 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 21 Apr 2015 17:42:53 +0200
Subject: Question about checking rate_spi in pwrap_init_reg_clock
In-Reply-To: <20150421125223.GB6325@pengutronix.de>
References: <1429581487.5994.1.camel@ingics.com>
 <20150421103155.GX6325@pengutronix.de>
 <CABuKBeJqgWHWNYaFXS-BwEayHEtiYGt+56LLXs3QaO3MHUk0bQ@mail.gmail.com>
 <20150421125223.GB6325@pengutronix.de>
Message-ID: <CABuKBeJMKpmkVZQvjZOuEtZmVaby6wxhr-i7w6eoHLjqTNNRig@mail.gmail.com>

2015-04-21 14:52 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Tue, Apr 21, 2015 at 01:43:19PM +0200, Matthias Brugger wrote:
>> 2015-04-21 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> > On Tue, Apr 21, 2015 at 09:58:07AM +0800, Axel Lin wrote:
>> >> hi,
>> >> The implementation in pwrap_init_reg_clock seems has off-by-one bug.
>> >> If rate_spi is 26000000, current code set ck_mhz to 18 rather than 26.
>> >>
>> >> I guess it needs below fix, but I'm not 100% sure as I don't have the datasheet.
>> >> Can someone confirm if this is a bug or not?
>> >
>> > Yes, seems to be a bug. Thanks for noting. Will you send a formal patch
>> > or should I do it?
>>
>> Did you have a look on both datasheets/reference kernels, mt8135 and mt8173?
>> Reading the datasheet and reference kernel code for mt6589 this SPI
>> waveform configuration looks like magic.
>>
>> But reading the clock frequency which can have clk_spi in mt8135, they
>> are 0 MHz, 26 MHz and bigger then 26 MHz, which leads me to the
>> conclusion that the code is correct. Otherwise the check for bigger
>> then 18 MHz is useless and should be deleted, if we have a similar
>> clock distribution in mt8173.
>
> The CSHEXT and CSLEXT registers extend the time the chipselect stays
> high after a SPI transfer or low before a new transfer by the given
> number of spi clk cycles.
> Looking at the code maybe the real question is not whether the border is
> at 25999999Hz or at 26000000Hz, but why the transfers are throttled with
> slower clock frequencies. I would assume the other way round makes
> sense.

After re-reading the data sheet and the reference kernel
implementation, it seems as if three clocks exist. clk_wrap and
clk_spi and "pmic reg_clk". And some how depending on the three clocks
you have to calculate the values for CSHEXT, CSLEXT etc.

I think we need some clarification here from Mediatek to really
understand what is going on.


From pi-cheng.chen at linaro.org  Tue Apr 21 20:11:34 2015
From: pi-cheng.chen at linaro.org (Pi-Cheng Chen)
Date: Wed, 22 Apr 2015 11:11:34 +0800
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>
Message-ID: <CALx668W6nJkYR325BhxOXMF1z=i7mkYbh3pyBFDNoZC9NZ0dVw@mail.gmail.com>

Hi Josh,

Thanks for reviewing.

On Mon, Apr 20, 2015 at 10:17 PM, Josh Cartwright <joshc at ni.com> wrote:
> On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
>> This patch implements MT8173 specific cpufreq driver with OPP table defined
>> in the driver code.
>>
>> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
>> ---
>>  drivers/cpufreq/Kconfig.arm      |   6 +
>>  drivers/cpufreq/Makefile         |   1 +
>>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 516 insertions(+)
>>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 1b06fc4..25643c7 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -132,6 +132,12 @@ config ARM_KIRKWOOD_CPUFREQ
>>         This adds the CPUFreq driver for Marvell Kirkwood
>>         SoCs.
>>
>> +config ARM_MT8173_CPUFREQ
>> +     bool "Mediatek MT8173 CPUFreq support"
>> +     depends on ARCH_MEDIATEK && REGULATOR
>
> I think you want to 'select REGULATOR' here; because REGULATOR isn't
> a user-visible option.

I am not sure but I need it to be "depends on" as other SoC cpufreq
drivers. Please check
ARM_S3C2416_CPUFREQ_VCORESCALE in drivers/cpufreq/Kconfig.arm
By the way, I would like to know more details about the visibility of
these configurable
options, would you kindly point me out some documents about it?

>
>> +     help
>> +       This adds the CPUFreq driver support for Mediatek MT8173 SoC.
>> +
>>  config ARM_OMAP2PLUS_CPUFREQ
>>       bool "TI OMAP2+"
>>       depends on ARCH_OMAP2PLUS
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 82a1821..da9d616 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)  += highbank-cpufreq.o
>>  obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)              += imx6q-cpufreq.o
>>  obj-$(CONFIG_ARM_INTEGRATOR)         += integrator-cpufreq.o
>>  obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)   += kirkwood-cpufreq.o
>> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)     += mt8173-cpufreq.o
>>  obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)  += omap-cpufreq.o
>>  obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)     += pxa2xx-cpufreq.o
>>  obj-$(CONFIG_PXA3xx)                 += pxa3xx-cpufreq.o
>> diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
>> new file mode 100644
>> index 0000000..a310e72
>> --- /dev/null
>> +++ b/drivers/cpufreq/mt8173-cpufreq.c
>> @@ -0,0 +1,509 @@
>> +/*
>> +* Copyright (c) 2015 Linaro Ltd.
>> +* Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
>> +*
>> +* 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.
>> +*/
>> +
>> +#include <linux/clk.h>
>> +#include <linux/cpu.h>
>> +#include <linux/cpufreq.h>
>> +#include <linux/cpumask.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/slab.h>
>> +
>> +#define MIN_VOLT_SHIFT               100000
>> +#define MAX_VOLT_SHIFT               200000
>> +
>> +#define OPP(f, vp, vs) {             \
>> +             .freq   = f,            \
>> +             .vproc  = vp,           \
>> +             .vsram  = vs,           \
>> +     }
>> +
>> +struct mtk_cpu_opp {
>> +     unsigned int freq;
>> +     int vproc;
>> +     int vsram;
>> +};
>> +
>> +/*
>> + * The struct cpu_dvfs_info holds necessary information for doing CPU DVFS of
>> + * each cluster. For Mediatek SoCs, each CPU cluster in SoC has two voltage
>> + * inputs, Vproc and Vsram. For some cluster in SoC, the two voltage inputs are
>> + * supplied by different PMICs. In this case, when scaling up/down the voltage
>> + * of Vsram and Vproc, the two voltage inputs need to be controlled under a
>> + * hardware limitation: 100mV < Vsram - Vproc < 200mV
>> + * When scaling up/down the clock frequency of a cluster, the clock source need
>> + * to be switched to another stable PLL clock temporarily, and switched back to
>> + * the original PLL after the it becomes stable at target frequency.
>> + * Hence the voltage inputs of cluster need to be set to an intermediate voltage
>> + * before the clock frequency being scaled up/down.
>> + */
>> +
>> +struct cpu_dvfs_info {
>> +     cpumask_t cpus;
>> +
>> +     struct mtk_cpu_opp *opp_tbl;
>> +     struct mtk_cpu_opp *intermediate_opp;
>> +     int nr_opp;
>> +
>> +     struct regulator *proc_reg;
>> +     struct regulator *sram_reg;
>> +     struct clk *cpu_clk;
>> +     struct clk *inter_pll;
>> +};
>> +
>> +/*
>> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
>> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
>> + * tree.
>> + */
>> +
>> +/* OPP table for LITTLE cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_l_opp[] = {
>
> static const?

Yes. I miss "static" here. But I need those two array to be non-const
so that I could
fix up the exact voltage values by querying the supported voltages of
regulators.
Please check the mt8173_cpufreq_cpu_opp_fixup() function below.

>
>> +     OPP(507000000, 859000, 0),
>> +     OPP(702000000, 908000, 0),
>> +     OPP(1001000000, 983000, 0),
>> +     OPP(1105000000, 1009000, 0),
>> +     OPP(1183000000, 1028000, 0),
>> +     OPP(1404000000, 1083000, 0),
>> +     OPP(1508000000, 1109000, 0),
>> +     OPP(1573000000, 1125000, 0),
>> +};
>> +
>> +/* OPP table for big cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_b_opp[] = {
>
> same here?
>
>> +     OPP(507000000, 828000, 928000),
>> +     OPP(702000000, 867000, 967000),
>> +     OPP(1001000000, 927000, 1027000),
>> +     OPP(1209000000, 968000, 1068000),
>> +     OPP(1404000000, 1007000, 1107000),
>> +     OPP(1612000000, 1049000, 1149000),
>> +     OPP(1807000000, 1089000, 1150000),
>> +     OPP(1989000000, 1125000, 1150000),
>> +};
>> +
> [..]
>> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
>> +                                  struct mtk_cpu_opp *opp)
>> +{
>> +     struct regulator *proc_reg = info->proc_reg;
>> +     struct regulator *sram_reg = info->sram_reg;
>> +     int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
>> +
>> +     old_vproc = regulator_get_voltage(proc_reg);
>> +     old_vsram = regulator_get_voltage(sram_reg);
>> +
>> +     new_vproc = opp->vproc;
>> +     new_vsram = opp->vsram;
>> +
>> +     /*
>> +      * In the case the voltage is going to be scaled up, Vsram and Vproc
>> +      * need to be scaled up step by step. In each step, Vsram needs to be
>> +      * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
>> +      * Repeat the step until Vsram and Vproc are set to target voltage.
>> +      */
>> +     if (old_vproc < new_vproc) {
>> +next_up_step:
>> +             old_vsram = regulator_get_voltage(sram_reg);
>> +
>> +             vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
>> +                     new_vsram : old_vproc + MAX_VOLT_SHIFT;
>> +             vsram = get_regulator_voltage_floor(sram_reg, vsram);
>> +
>> +             ret = regulator_set_voltage(sram_reg, vsram, vsram);
>> +             if (ret)
>> +                     return ret;
>> +
>> +             vproc = (new_vsram == vsram) ?
>> +                     new_vproc : vsram - MIN_VOLT_SHIFT;
>> +             vproc = get_regulator_voltage_ceil(proc_reg, vproc);
>> +
>> +             ret = regulator_set_voltage(proc_reg, vproc, vproc);
>> +             if (ret) {
>> +                     regulator_set_voltage(sram_reg, old_vsram, old_vsram);
>> +                     return ret;
>> +             }
>> +
>> +             if (new_vproc == vproc && new_vsram == vsram)
>> +                     return 0;
>> +
>> +             old_vproc = vproc;
>> +             goto next_up_step;
>
> Perhaps a naive question: but, is this the correct place to do this?  I
> would expect this stepping behavior to be implemented in the driver
> controlling the regulator you are consuming.  It seems strange to do it
> here.

This was already discussed in the last round of this series of patches.
Please check the discussion[1]. Any suggestion would be welcomed.
Thanks.

[1] http://article.gmane.org/gmane.linux.kernel/1905909

Best Regards,
Pi-Cheng

>
>   Josh


From pi-cheng.chen at linaro.org  Tue Apr 21 20:14:50 2015
From: pi-cheng.chen at linaro.org (Pi-Cheng Chen)
Date: Wed, 22 Apr 2015 11:14:50 +0800
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429554517.14597.38.camel@x220>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <1429554517.14597.38.camel@x220>
Message-ID: <CALx668VD7KZv1ejRsWTtZ=EKPej6mEi3ahdhKPoOEwd+oD-QYA@mail.gmail.com>

On Tue, Apr 21, 2015 at 2:28 AM, Paul Bolle <pebolle at tiscali.nl> wrote:
> On Mon, 2015-04-20 at 17:27 +0800, pi-cheng.chen wrote:
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>
>> +config ARM_MT8173_CPUFREQ
>> +     bool "Mediatek MT8173 CPUFreq support"
>> +     depends on ARCH_MEDIATEK && REGULATOR
>> +     help
>> +       This adds the CPUFreq driver support for Mediatek MT8173 SoC.
>
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>
>> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)     += mt8173-cpufreq.o
>
> ARM_MT8173_CPUFREQ is a bool symbol, so mt8173-cpufreq.o will never be
> part of a module.
>
> (If that's incorrect you can stop reading here.)
>
>> --- /dev/null
>> +++ b/drivers/cpufreq/mt8173-cpufreq.c
>
>> +#include <linux/module.h>
>
> I guess this include is not needed. And, for what it's worth,
>     make ARCH=arm CROSS_COMPILE=arm-linux-gnu- drivers/cpufreq/mt8173-cpufreq.o
>
> compiles silently even if it's dropped.
>
>> +module_init(mt8173_cpufreq_driver_init);
>
> According to include/linux/init.h, for built-in only code, this is
> equivalent to device_initcall([...]). And two runs of
>     make ARCH=arm CROSS_COMPILE=arm-linux-gnu- drivers/cpufreq/mt8173-cpufreq.i
>
> confirm that.

Hi Paul,

Thanks for your reviewing.
The <linux/module.h> is not needed here.
I'll remove it.

Best Regards,
Pi-Cheng

>
> Thanks,
>
>
> Paul Bolle
>


From koro.chen at mediatek.com  Tue Apr 21 20:17:20 2015
From: koro.chen at mediatek.com (Koro Chen)
Date: Wed, 22 Apr 2015 11:17:20 +0800
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <20150420204849.GJ14892@sirena.org.uk>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
Message-ID: <1429672640.14162.55.camel@mtksdaap41>

On Mon, 2015-04-20 at 21:48 +0100, Mark Brown wrote:
> On Mon, Apr 20, 2015 at 06:37:47AM +0200, Sascha Hauer wrote:
> > On Sat, Apr 18, 2015 at 06:34:07PM +0100, Mark Brown wrote:
> > > On Fri, Apr 10, 2015 at 04:14:07PM +0800, Koro Chen wrote:
> 
> > > > +Each external interface (called "IO" in this driver) is presented as a
> > > > +DAI to ASoC. An IO must be connected via the interconnect to a memif.
> > > > +The connection paths are configured through the device tree.
> 
> > > Why are these connection paths configured via device tree?  I would
> > > expect that either there would be runtime configurability of these
> > > things (particularly if loopback configurations within the hardware are
> > > possible) or we'd just allocate memory interfaces to DAIs automatically
> > > as DAIs come into use.
> 
> > There is a crossbar switch between the memory interfaces and the DAIs.
> > Not every connection is possible, so not every memory interface can be
> > used for every DAI. An algorithm choosing a suitable memory interface
> > must be quite clever, complicated and also SoC dependent (the same but
> > different hardware is used on MT8135 aswell), so I thought offering a
> > static configuration via device tree is a good start. Should there be
> > runtime configuration possible later the device tree settings could
> > provide a good default.
> 
> What exactly do the restrictions look like and how often do they vary in
> practice (can we get away with just doing a single static setup in the
> driver)?  I'd have thought it should be fairly straightforward to have a
> table of valid mappings and just pick the first free memory interface?
> I'd rather not get stuck with the tables in the DT.  It's partly to
> avoid setting bad precendents, we really don't want everyone coming
> along hard coding this stuff, and partly because the hardware you
> described didn't seem that hard to handle.
> 
If using DPCM, it seems the most suitable FE DAIs will be memif, and
external interface like I2S should be BE DAIs. Do you think it is
suitable for our memif to be FE DAIs? Then which memif to used can be
described in a machine driver's FE DAIs. But I think this has a problem
that our memif is one-direction, playback or capture. So the binded pcm
device cannot have playback and capture capability together. May it
cause trouble for user space apps that assumes there will be pcmC0D0p,
pcmC0D0c?

> > > > +- mem-interface-playback:
> > > > +  mem-interface-capture: property of memif, format is: <memif irq use_sram>;
> > > > +	                 memif: which memif to be used
> > > > +			        (defined in include/dt-bindings/sound/mtk-afe.h)
> > > > +		         irq: which irq to be used
> > > > +			      (defined in include/dt-bindings/sound/mtk-afe.h)
> > > > +		         use_sram: 1 is yes, 0 is no
> 
> > > Again, this looks like stuff we should be able to figure out at runtime
> > > - the use of SRAM in particular looks like something we might want to
> > > change depending on use case.  Assuming it adds buffering then for a
> > > VoIP application we might not want to use SRAM to minimize latency but
> > > during music playback we might want to enable SRAM to minimize power
> > > consumption.
> 
> > That's exactly the usecase. How could such a runtime configurability
> > look like? sysfs? Or something based on the buffer sizes?
> 
> Yeah, one of those :) but probably an ALSA control is going to be the
> easiest for applications.




From joshc at ni.com  Wed Apr 22 07:33:52 2015
From: joshc at ni.com (Josh Cartwright)
Date: Wed, 22 Apr 2015 09:33:52 -0500
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <CALx668W6nJkYR325BhxOXMF1z=i7mkYbh3pyBFDNoZC9NZ0dVw@mail.gmail.com>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150420141719.GF27115@jcartwri.amer.corp.natinst.com>
 <CALx668W6nJkYR325BhxOXMF1z=i7mkYbh3pyBFDNoZC9NZ0dVw@mail.gmail.com>
Message-ID: <20150422143352.GJ27115@jcartwri.amer.corp.natinst.com>

On Wed, Apr 22, 2015 at 11:11:34AM +0800, Pi-Cheng Chen wrote:
[..]
> >> +config ARM_MT8173_CPUFREQ
> >> +     bool "Mediatek MT8173 CPUFreq support"
> >> +     depends on ARCH_MEDIATEK && REGULATOR
> >
> > I think you want to 'select REGULATOR' here; because REGULATOR isn't
> > a user-visible option.
> 
> I am not sure but I need it to be "depends on" as other SoC cpufreq
> drivers. Please check
> ARM_S3C2416_CPUFREQ_VCORESCALE in drivers/cpufreq/Kconfig.arm
> By the way, I would like to know more details about the visibility of
> these configurable
> options, would you kindly point me out some documents about it?

Paul pointed out that I was wrong, so I'll defer to him.  My knowledge
has likely been outdated.

[..]
> >> +/* OPP table for LITTLE cores of MT8173 */
> >> +struct mtk_cpu_opp mt8173_l_opp[] = {
> >
> > static const?
> 
> Yes. I miss "static" here. But I need those two array to be non-const
> so that I could
> fix up the exact voltage values by querying the supported voltages of
> regulators.
> Please check the mt8173_cpufreq_cpu_opp_fixup() function below.

Indeed.  Thanks.

[..]
> >> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
> >> +                                  struct mtk_cpu_opp *opp)
> >> +{
> >> +     struct regulator *proc_reg = info->proc_reg;
> >> +     struct regulator *sram_reg = info->sram_reg;
> >> +     int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
> >> +
> >> +     old_vproc = regulator_get_voltage(proc_reg);
> >> +     old_vsram = regulator_get_voltage(sram_reg);
> >> +
> >> +     new_vproc = opp->vproc;
> >> +     new_vsram = opp->vsram;
> >> +
> >> +     /*
> >> +      * In the case the voltage is going to be scaled up, Vsram and Vproc
> >> +      * need to be scaled up step by step. In each step, Vsram needs to be
> >> +      * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
> >> +      * Repeat the step until Vsram and Vproc are set to target voltage.
> >> +      */
> >> +     if (old_vproc < new_vproc) {
> >> +next_up_step:
> >> +             old_vsram = regulator_get_voltage(sram_reg);
> >> +
> >> +             vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
> >> +                     new_vsram : old_vproc + MAX_VOLT_SHIFT;
> >> +             vsram = get_regulator_voltage_floor(sram_reg, vsram);
> >> +
> >> +             ret = regulator_set_voltage(sram_reg, vsram, vsram);
> >> +             if (ret)
> >> +                     return ret;
> >> +
> >> +             vproc = (new_vsram == vsram) ?
> >> +                     new_vproc : vsram - MIN_VOLT_SHIFT;
> >> +             vproc = get_regulator_voltage_ceil(proc_reg, vproc);
> >> +
> >> +             ret = regulator_set_voltage(proc_reg, vproc, vproc);
> >> +             if (ret) {
> >> +                     regulator_set_voltage(sram_reg, old_vsram, old_vsram);
> >> +                     return ret;
> >> +             }
> >> +
> >> +             if (new_vproc == vproc && new_vsram == vsram)
> >> +                     return 0;
> >> +
> >> +             old_vproc = vproc;
> >> +             goto next_up_step;
> >
> > Perhaps a naive question: but, is this the correct place to do this?  I
> > would expect this stepping behavior to be implemented in the driver
> > controlling the regulator you are consuming.  It seems strange to do it
> > here.
> 
> This was already discussed in the last round of this series of patches.
> Please check the discussion[1]. Any suggestion would be welcomed.
> Thanks.

Interesting, thanks.  Sorry for rehashing already-covered territory!

  Josh
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150422/0c3b0988/attachment-0001.sig>

From s.hauer at pengutronix.de  Thu Apr 23 01:35:41 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:41 +0200
Subject: [PATCH 4/6] clk: mediatek: Add basic clocks for Mediatek MT8135.
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-5-git-send-email-s.hauer@pengutronix.de>

From: James Liao <jamesjj.liao at mediatek.com>

This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
INFRA and PERI clocks.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/mediatek/Makefile                      |   1 +
 drivers/clk/mediatek/clk-mt8135.c                  | 644 +++++++++++++++++++++
 include/dt-bindings/clock/mt8135-clk.h             | 194 +++++++
 .../dt-bindings/reset-controller/mt8135-resets.h   |  64 ++
 4 files changed, 903 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8135.c
 create mode 100644 include/dt-bindings/clock/mt8135-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 0b6f1c3..12ce576 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,2 +1,3 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 0000000..a63435b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/mt8135-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static DEFINE_SPINLOCK(mt8135_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
+	FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+	FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+	FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
+	FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
+
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
+
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
+
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
+
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
+	FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
+	FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
+	FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
+	FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
+	FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
+
+	FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
+	FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
+
+	FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d4",
+	"syspll_d6",
+	"univpll_d5",
+	"univpll2_d2",
+	"syspll_d3p5"
+};
+
+static const char * const smi_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll1_d6",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7",
+	"vdecpll",
+	"lvdspll"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d4",
+	"syspll_d2",
+	"syspll_d2p5",
+	"syspll_d3",
+	"univpll_d5",
+	"univpll1_d2",
+	"mmpll_d2",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll1_d6"
+};
+
+static const char * const cam_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll1_d4"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"univpll_d10"
+};
+
+static const char * const jpg_parents[] __initconst = {
+	"clk26m",
+	"syspll_d5",
+	"syspll_d4",
+	"syspll_d3",
+	"univpll_d7",
+	"univpll2_d2",
+	"univpll_d5"
+};
+
+static const char * const disp_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3p5",
+	"syspll_d3",
+	"univpll2_d2",
+	"univpll_d5",
+	"univpll1_d2",
+	"lvdspll",
+	"vdecpll"
+};
+
+static const char * const msdc30_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d5",
+	"univpll1_d4",
+	"univpll2_d4",
+	"msdcpll"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"univpll1_d10"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d6",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll1_d6",
+	"syspll_d16",
+	"syspll_d8"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll_d24"
+};
+
+static const char * const fix_parents[] __initconst = {
+	"rtc32k",
+	"clk26m",
+	"univpll_d5",
+	"univpll_d7",
+	"univpll1_d2",
+	"univpll1_d4",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vdecpll",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"syspll_d5",
+	"syspll_d6",
+	"syspll_d8",
+	"univpll1_d2",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll_d10",
+	"univpll2_d4",
+	"lvdspll"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"syspll_d12"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d10",
+	"mempll_mck_d4",
+	"univpll_d26",
+	"syspll_d24"
+};
+
+static const char * const smi_mfg_as_parents[] __initconst = {
+	"clk26m",
+	"smi_sel",
+	"mfg_sel",
+	"mem_sel"
+};
+
+static const char * const gcpu_parents[] __initconst = {
+	"clk26m",
+	"syspll_d4",
+	"univpll_d7",
+	"syspll_d5",
+	"syspll_d6"
+};
+
+static const char * const dpi1_parents[] __initconst = {
+	"clk26m",
+	"tvhdmi_h_ck",
+	"tvhdmi_d2",
+	"tvhdmi_d4"
+};
+
+static const char * const cci_parents[] __initconst = {
+	"clk26m",
+	"mainpll_537p3m",
+	"univpll_d3",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d5"
+};
+
+static const char * const apll_parents[] __initconst = {
+	"clk26m",
+	"apll_ck",
+	"apll_d4",
+	"apll_d8",
+	"apll_d16",
+	"apll_d24"
+};
+
+static const char * const hdmipll_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_clkdig_cts",
+	"hdmitx_clkdig_d2",
+	"hdmitx_clkdig_d3"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+	MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0144, 8, 2, 15),
+	MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
+	MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+		0x015c, 16, 2, 23),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
+	/* CLK_CFG_8 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
+		0x0164, 16, 2, 23),
+	MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
+	/* CLK_CFG_9 */
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
+	MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
+	GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
+	GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
+	GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
+	GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
+	GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
+	GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
+	GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8135_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8135_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
+
+#define MT8135_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8135_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8135_RST_BAR,			\
+		.fmax = MT8135_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 0000000..6dac6c0
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_DSI0_LNTC_DSICLK	1
+#define CLK_TOP_HDMITX_CLKDIG_CTS	2
+#define CLK_TOP_CLKPH_MCK		3
+#define CLK_TOP_CPUM_TCK_IN		4
+#define CLK_TOP_MAINPLL_806M		5
+#define CLK_TOP_MAINPLL_537P3M		6
+#define CLK_TOP_MAINPLL_322P4M		7
+#define CLK_TOP_MAINPLL_230P3M		8
+#define CLK_TOP_UNIVPLL_624M		9
+#define CLK_TOP_UNIVPLL_416M		10
+#define CLK_TOP_UNIVPLL_249P6M		11
+#define CLK_TOP_UNIVPLL_178P3M		12
+#define CLK_TOP_UNIVPLL_48M		13
+#define CLK_TOP_MMPLL_D2		14
+#define CLK_TOP_MMPLL_D3		15
+#define CLK_TOP_MMPLL_D5		16
+#define CLK_TOP_MMPLL_D7		17
+#define CLK_TOP_MMPLL_D4		18
+#define CLK_TOP_MMPLL_D6		19
+#define CLK_TOP_SYSPLL_D2		20
+#define CLK_TOP_SYSPLL_D4		21
+#define CLK_TOP_SYSPLL_D6		22
+#define CLK_TOP_SYSPLL_D8		23
+#define CLK_TOP_SYSPLL_D10		24
+#define CLK_TOP_SYSPLL_D12		25
+#define CLK_TOP_SYSPLL_D16		26
+#define CLK_TOP_SYSPLL_D24		27
+#define CLK_TOP_SYSPLL_D3		28
+#define CLK_TOP_SYSPLL_D2P5		29
+#define CLK_TOP_SYSPLL_D5		30
+#define CLK_TOP_SYSPLL_D3P5		31
+#define CLK_TOP_UNIVPLL1_D2		32
+#define CLK_TOP_UNIVPLL1_D4		33
+#define CLK_TOP_UNIVPLL1_D6		34
+#define CLK_TOP_UNIVPLL1_D8		35
+#define CLK_TOP_UNIVPLL1_D10		36
+#define CLK_TOP_UNIVPLL2_D2		37
+#define CLK_TOP_UNIVPLL2_D4		38
+#define CLK_TOP_UNIVPLL2_D6		39
+#define CLK_TOP_UNIVPLL2_D8		40
+#define CLK_TOP_UNIVPLL_D3		41
+#define CLK_TOP_UNIVPLL_D5		42
+#define CLK_TOP_UNIVPLL_D7		43
+#define CLK_TOP_UNIVPLL_D10		44
+#define CLK_TOP_UNIVPLL_D26		45
+#define CLK_TOP_APLL			46
+#define CLK_TOP_APLL_D4			47
+#define CLK_TOP_APLL_D8			48
+#define CLK_TOP_APLL_D16		49
+#define CLK_TOP_APLL_D24		50
+#define CLK_TOP_LVDSPLL_D2		51
+#define CLK_TOP_LVDSPLL_D4		52
+#define CLK_TOP_LVDSPLL_D8		53
+#define CLK_TOP_LVDSTX_CLKDIG_CT	54
+#define CLK_TOP_VPLL_DPIX		55
+#define CLK_TOP_TVHDMI_H		56
+#define CLK_TOP_HDMITX_CLKDIG_D2	57
+#define CLK_TOP_HDMITX_CLKDIG_D3	58
+#define CLK_TOP_TVHDMI_D2		59
+#define CLK_TOP_TVHDMI_D4		60
+#define CLK_TOP_MEMPLL_MCK_D4		61
+#define CLK_TOP_AXI_SEL			62
+#define CLK_TOP_SMI_SEL			63
+#define CLK_TOP_MFG_SEL			64
+#define CLK_TOP_IRDA_SEL		65
+#define CLK_TOP_CAM_SEL			66
+#define CLK_TOP_AUD_INTBUS_SEL		67
+#define CLK_TOP_JPG_SEL			68
+#define CLK_TOP_DISP_SEL		69
+#define CLK_TOP_MSDC30_1_SEL		70
+#define CLK_TOP_MSDC30_2_SEL		71
+#define CLK_TOP_MSDC30_3_SEL		72
+#define CLK_TOP_MSDC30_4_SEL		73
+#define CLK_TOP_USB20_SEL		74
+#define CLK_TOP_VENC_SEL		75
+#define CLK_TOP_SPI_SEL			76
+#define CLK_TOP_UART_SEL		77
+#define CLK_TOP_MEM_SEL			78
+#define CLK_TOP_CAMTG_SEL		79
+#define CLK_TOP_AUDIO_SEL		80
+#define CLK_TOP_FIX_SEL			81
+#define CLK_TOP_VDEC_SEL		82
+#define CLK_TOP_DDRPHYCFG_SEL		83
+#define CLK_TOP_DPILVDS_SEL		84
+#define CLK_TOP_PMICSPI_SEL		85
+#define CLK_TOP_MSDC30_0_SEL		86
+#define CLK_TOP_SMI_MFG_AS_SEL		87
+#define CLK_TOP_GCPU_SEL		88
+#define CLK_TOP_DPI1_SEL		89
+#define CLK_TOP_CCI_SEL			90
+#define CLK_TOP_APLL_SEL		91
+#define CLK_TOP_HDMIPLL_SEL		92
+#define CLK_TOP_NR_CLK			93
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMPLL1		1
+#define CLK_APMIXED_ARMPLL2		2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_TVDPLL		7
+#define CLK_APMIXED_LVDSPLL		8
+#define CLK_APMIXED_AUDPLL		9
+#define CLK_APMIXED_VDECPLL		10
+#define CLK_APMIXED_NR_CLK		11
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_PMIC_WRAP		1
+#define CLK_INFRA_PMICSPI		2
+#define CLK_INFRA_CCIF1_AP_CTRL		3
+#define CLK_INFRA_CCIF0_AP_CTRL		4
+#define CLK_INFRA_KP			5
+#define CLK_INFRA_CPUM			6
+#define CLK_INFRA_M4U			7
+#define CLK_INFRA_MFGAXI		8
+#define CLK_INFRA_DEVAPC		9
+#define CLK_INFRA_AUDIO			10
+#define CLK_INFRA_MFG_BUS		11
+#define CLK_INFRA_SMI			12
+#define CLK_INFRA_DBGCLK		13
+#define CLK_INFRA_NR_CLK		14
+
+/* PERI_SYS */
+
+#define CLK_PERI_I2C5			1
+#define CLK_PERI_I2C4			2
+#define CLK_PERI_I2C3			3
+#define CLK_PERI_I2C2			4
+#define CLK_PERI_I2C1			5
+#define CLK_PERI_I2C0			6
+#define CLK_PERI_UART3			7
+#define CLK_PERI_UART2			8
+#define CLK_PERI_UART1			9
+#define CLK_PERI_UART0			10
+#define CLK_PERI_IRDA			11
+#define CLK_PERI_NLI			12
+#define CLK_PERI_MD_HIF			13
+#define CLK_PERI_AP_HIF			14
+#define CLK_PERI_MSDC30_3		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_1		17
+#define CLK_PERI_MSDC20_2		18
+#define CLK_PERI_MSDC20_1		19
+#define CLK_PERI_AP_DMA			20
+#define CLK_PERI_USB1			21
+#define CLK_PERI_USB0			22
+#define CLK_PERI_PWM			23
+#define CLK_PERI_PWM7			24
+#define CLK_PERI_PWM6			25
+#define CLK_PERI_PWM5			26
+#define CLK_PERI_PWM4			27
+#define CLK_PERI_PWM3			28
+#define CLK_PERI_PWM2			29
+#define CLK_PERI_PWM1			30
+#define CLK_PERI_THERM			31
+#define CLK_PERI_NFI			32
+#define CLK_PERI_USBSLV			33
+#define CLK_PERI_USB1_MCU		34
+#define CLK_PERI_USB0_MCU		35
+#define CLK_PERI_GCPU			36
+#define CLK_PERI_FHCTL			37
+#define CLK_PERI_SPI1			38
+#define CLK_PERI_AUXADC			39
+#define CLK_PERI_PERI_PWRAP		40
+#define CLK_PERI_I2C6			41
+#define CLK_PERI_UART0_SEL		42
+#define CLK_PERI_UART1_SEL		43
+#define CLK_PERI_UART2_SEL		44
+#define CLK_PERI_UART3_SEL		45
+#define CLK_PERI_NR_CLK			46
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 0000000..1fb6295
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST        0
+#define MT8135_INFRA_DRAMC0_A0_RST      1
+#define MT8135_INFRA_CCIF0_RST          2
+#define MT8135_INFRA_APCIRQ_EINT_RST    3
+#define MT8135_INFRA_APXGPT_RST         4
+#define MT8135_INFRA_SCPSYS_RST         5
+#define MT8135_INFRA_CCIF1_RST          6
+#define MT8135_INFRA_PMIC_WRAP_RST      7
+#define MT8135_INFRA_KP_RST             8
+#define MT8135_INFRA_EMI_RST            32
+#define MT8135_INFRA_DRAMC0_RST         34
+#define MT8135_INFRA_SMI_RST            35
+#define MT8135_INFRA_M4U_RST            36
+
+/*  PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST        0
+#define MT8135_PERI_UART1_SW_RST        1
+#define MT8135_PERI_UART2_SW_RST        2
+#define MT8135_PERI_UART3_SW_RST        3
+#define MT8135_PERI_IRDA_SW_RST         4
+#define MT8135_PERI_PTP_SW_RST          5
+#define MT8135_PERI_AP_HIF_SW_RST       6
+#define MT8135_PERI_GPCU_SW_RST         7
+#define MT8135_PERI_MD_HIF_SW_RST       8
+#define MT8135_PERI_NLI_SW_RST          9
+#define MT8135_PERI_AUXADC_SW_RST       10
+#define MT8135_PERI_DMA_SW_RST          11
+#define MT8135_PERI_NFI_SW_RST          14
+#define MT8135_PERI_PWM_SW_RST          15
+#define MT8135_PERI_THERM_SW_RST        16
+#define MT8135_PERI_MSDC0_SW_RST        17
+#define MT8135_PERI_MSDC1_SW_RST        18
+#define MT8135_PERI_MSDC2_SW_RST        19
+#define MT8135_PERI_MSDC3_SW_RST        20
+#define MT8135_PERI_I2C0_SW_RST         22
+#define MT8135_PERI_I2C1_SW_RST         23
+#define MT8135_PERI_I2C2_SW_RST         24
+#define MT8135_PERI_I2C3_SW_RST         25
+#define MT8135_PERI_I2C4_SW_RST         26
+#define MT8135_PERI_I2C5_SW_RST         27
+#define MT8135_PERI_I2C6_SW_RST         28
+#define MT8135_PERI_USB_SW_RST          29
+#define MT8135_PERI_SPI1_SW_RST         33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:35:43 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:43 +0200
Subject: [PATCH 6/6] dt-bindings: ARM: Mediatek: Document devicetree bindings
 for clock/reset controllers
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-7-git-send-email-s.hauer@pengutronix.de>

This adds the binding documentation for the apmixedsys, perisys and
infracfg controllers found on Mediatek SoCs.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  | 23 +++++++++++++++++
 .../bindings/arm/mediatek/mediatek,infracfg.txt    | 30 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,pericfg.txt     | 30 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,topckgen.txt    | 23 +++++++++++++++++
 4 files changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
new file mode 100644
index 0000000..5af6d73
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -0,0 +1,23 @@
+Mediatek apmixedsys controller
+==============================
+
+The Mediatek apmixedsys controller provides the PLLs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-apmixedsys"
+	- "mediatek,mt8173-apmixedsys"
+- #clock-cells: Must be 1
+
+The apmixedsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+apmixedsys: apmixedsys at 10209000 {
+	compatible = "mediatek,mt8173-apmixedsys";
+	reg = <0 0x10209000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
new file mode 100644
index 0000000..684da473
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -0,0 +1,30 @@
+Mediatek infracfg controller
+============================
+
+The Mediatek infracfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-infracfg", "syscon"
+	- "mediatek,mt8173-infracfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The infracfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+infracfg: infracfg at 10001000 {
+	compatible = "mediatek,mt8173-infracfg", "syscon";
+	reg = <0 0x10001000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
new file mode 100644
index 0000000..fdb45c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -0,0 +1,30 @@
+Mediatek pericfg controller
+===========================
+
+The Mediatek pericfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-pericfg", "syscon"
+	- "mediatek,mt8173-pericfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The pericfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+pericfg: pericfg at 10003000 {
+	compatible = "mediatek,mt8173-pericfg", "syscon";
+	reg = <0 0x10003000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
new file mode 100644
index 0000000..a425248
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -0,0 +1,23 @@
+Mediatek topckgen controller
+============================
+
+The Mediatek topckgen controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-topckgen"
+	- "mediatek,mt8173-topckgen"
+- #clock-cells: Must be 1
+
+The topckgen controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+topckgen: topckgen at 10000000 {
+	compatible = "mediatek,mt8173-topckgen";
+	reg = <0 0x10000000 0 0x1000>;
+	#clock-cells = <1>;
+};
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:35:37 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:37 +0200
Subject: [PATCH v12] clk: Add common clock support for Mediatek MT8135 and
 MT8173
Message-ID: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>

The following changes since commit 39a8804455fb23f09157341d3ba7db6d7ae6ee76:

  Linux 4.0 (2015-04-12 15:12:50 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/sha/linux-2.6.git tags/v4.0-clk-mediatek-v12

for you to fetch changes up to e0ebeaa8a3f4a762cb9c2780170445aad15915d1:

  dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-04-23 10:22:34 +0200)

----------------------------------------------------------------
This patchset contains the initial common clock support for Mediatek SoCs.
Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
and clock gates.

Changes in v12:
- Fix UART clocks: Add clocks providing the baudrate
- enable necessary but unused clocks for surviving the disabling
  of unused clocks
- cleanup clock define names: remove _CK suffix and consistently
  add a CLK_ prefix
- add and use mtk_clk_register_composites() for registering multiple
  composite clocks

Changes in v11:
- Use more defines in PLL code
- drop unused pr_fmt
- use i++ instead of ++i in two places

Changes in v10:
- polish some commit messages

Changes in v9:
- rename 'lock' to 'mt81xx_clk_lock' to get better lockdep output

Changes in v8:
- add patch to allow to put parent_name arrays in __initconst
- put parent_name arrays into __initconst

Changes in v7:
- fix duplicate definition/declaration of mtk_register_reset_controller
- fix pd_reg offset of tvdpll
- make clk initialization arrays const

Changes in v6:
- rework PLL support, only a fraction of original size now
- Move binding docs to Documentation/devicetree/bindings/arm/mediatek since
  the units are not really clock specific (they contain reset controllers)

Changes in v5:
- Add reset controller support for pericfg/infracfg
- Use regmap for the gates
- remove now unnecessary spinlock for the gates
- Add PMIC wrapper support as of v3

Changes in v4:
- Support MT8173 platform.
- Re-ordered patchset. driver/clk/Makefile in 2nd patch.
- Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from
  clk-mt8135.c/clk-mt8173.c to clk-mtk.c.
- Refine code. Rmove unnessacary debug information and unsed defines,
  add prefix "mtk_" for static functions.
- Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on
  gate/mux/fixed-factor.
- Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock.
- Example above include a node for the clock controller itself, followed
  by the i2c controller example above.

Changes in v3:
- Rebase to 3.19-rc1.
- Refine code. Remove unneed functions, debug logs and comments, and fine tune
  error logs.

Changes in v2:
- Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch.

----------------------------------------------------------------
James Liao (3):
      clk: mediatek: Add initial common clock support for Mediatek SoCs.
      clk: mediatek: Add basic clocks for Mediatek MT8135.
      clk: mediatek: Add basic clocks for Mediatek MT8173.

Sascha Hauer (3):
      clk: make strings in parent name arrays const
      clk: mediatek: Add reset controller support
      dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers

 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |  23 +
 .../bindings/arm/mediatek/mediatek,infracfg.txt    |  30 +
 .../bindings/arm/mediatek/mediatek,pericfg.txt     |  30 +
 .../bindings/arm/mediatek/mediatek,topckgen.txt    |  23 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-composite.c                        |   2 +-
 drivers/clk/clk-mux.c                              |   4 +-
 drivers/clk/mediatek/Makefile                      |   4 +
 drivers/clk/mediatek/clk-gate.c                    | 137 ++++
 drivers/clk/mediatek/clk-gate.h                    |  49 ++
 drivers/clk/mediatek/clk-mt8135.c                  | 644 ++++++++++++++++
 drivers/clk/mediatek/clk-mt8173.c                  | 830 +++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c                     | 220 ++++++
 drivers/clk/mediatek/clk-mtk.h                     | 169 +++++
 drivers/clk/mediatek/clk-pll.c                     | 332 +++++++++
 drivers/clk/mediatek/reset.c                       |  97 +++
 include/dt-bindings/clock/mt8135-clk.h             | 194 +++++
 include/dt-bindings/clock/mt8173-clk.h             | 235 ++++++
 .../dt-bindings/reset-controller/mt8135-resets.h   |  64 ++
 .../dt-bindings/reset-controller/mt8173-resets.h   |  63 ++
 include/linux/clk-provider.h                       |   8 +-
 21 files changed, 3152 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-gate.c
 create mode 100644 drivers/clk/mediatek/clk-gate.h
 create mode 100644 drivers/clk/mediatek/clk-mt8135.c
 create mode 100644 drivers/clk/mediatek/clk-mt8173.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h
 create mode 100644 drivers/clk/mediatek/clk-pll.c
 create mode 100644 drivers/clk/mediatek/reset.c
 create mode 100644 include/dt-bindings/clock/mt8135-clk.h
 create mode 100644 include/dt-bindings/clock/mt8173-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h
 create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h



From s.hauer at pengutronix.de  Thu Apr 23 01:35:42 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:42 +0200
Subject: [PATCH 5/6] clk: mediatek: Add basic clocks for Mediatek MT8173.
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-6-git-send-email-s.hauer@pengutronix.de>

From: James Liao <jamesjj.liao at mediatek.com>

This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs,
INFRA and PERI clocks.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/mediatek/Makefile                      |   1 +
 drivers/clk/mediatek/clk-mt8173.c                  | 830 +++++++++++++++++++++
 include/dt-bindings/clock/mt8173-clk.h             | 235 ++++++
 .../dt-bindings/reset-controller/mt8173-resets.h   |  63 ++
 4 files changed, 1129 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8173.c
 create mode 100644 include/dt-bindings/clock/mt8173-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 12ce576..8e4b2a4 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,3 +1,4 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 obj-y += clk-mt8135.o
+obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
new file mode 100644
index 0000000..357b080
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+static DEFINE_SPINLOCK(mt8173_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
+	FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
+
+	FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
+
+	FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
+	FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
+	FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+	FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+
+	FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+	FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
+	FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
+
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+
+	FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
+	FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
+
+	FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
+	FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
+	FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] __initconst = {
+	"clk26m",
+	"vencpll_d2",
+	"main_h364m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2"
+};
+
+static const char * const pwm_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"mmpll_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"univpll_d3",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll2_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"univpll1_d4"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const usb30_parents[] __initconst = {
+	"clk26m",
+	"univpll3_d2",
+	"usb_syspll_125m",
+	"univpll2_d4"
+};
+
+static const char * const msdc50_0_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const msdc50_0_parents[] __initconst = {
+	"clk26m",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"msdcpll_d4",
+	"vencpll_d4",
+	"tvdpll_ck",
+	"univpll_d2",
+	"univpll1_d2",
+	"mmpll_ck",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"msdcpll2_d4"
+};
+
+static const char * const msdc30_1_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4"
+};
+
+static const char * const msdc30_2_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d2"
+};
+
+static const char * const msdc30_3_parents[] __initconst = {
+	"clk26m",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"univpll2_d2",
+	"msdcpll2_d4",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"msdcpll_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d4",
+	"syspll4_d4",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d8",
+	"dmpll_d4",
+	"dmpll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll3_d4",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d8",
+	"dmpll_d16"
+};
+
+static const char * const scp_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const atb_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"dmpll_d2"
+};
+
+static const char * const venc_lt_parents[] __initconst = {
+	"clk26m",
+	"univpll_d3",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"syspll1_d2",
+	"univpll_d5",
+	"vcodecpll_370p5",
+	"dmpll_ck"
+};
+
+static const char * const dpi0_parents[] __initconst = {
+	"clk26m",
+	"tvdpll_d2",
+	"tvdpll_d4",
+	"clk26m",
+	"clk26m",
+	"tvdpll_d8",
+	"tvdpll_d16"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"syspll2_d4"
+};
+
+static const char * const cci400_parents[] __initconst = {
+	"clk26m",
+	"vencpll_ck",
+	"armca7pll_754m",
+	"armca7pll_502m",
+	"univpll_d2",
+	"syspll_d2",
+	"msdcpll_ck",
+	"dmpll_ck"
+};
+
+static const char * const aud_1_parents[] __initconst = {
+	"clk26m",
+	"apll1_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const aud_2_parents[] __initconst = {
+	"clk26m",
+	"apll2_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const mem_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m"
+};
+
+static const char * const axi_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"dmpll_d2"
+};
+
+static const char * const scam_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"univpll2_d4",
+	"dmpll_d4"
+};
+
+static const char * const spinfi_ifr_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll3_d4",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll3_d2",
+	"syspll1_d4",
+	"univpll1_d4"
+};
+
+static const char * const hdmi_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_dig_cts",
+	"hdmitxpll_d2",
+	"hdmitxpll_d3"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8",
+	"fpc_ck"
+};
+
+static const char * const msdc50_2_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const hdcp_parents[] __initconst = {
+	"clk26m",
+	"syspll4_d2",
+	"syspll3_d4",
+	"univpll2_d4"
+};
+
+static const char * const hdcp_24m_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll2_d8"
+};
+
+static const char * const rtc_parents[] __initconst = {
+	"clkrtc_int",
+	"clkrtc_ext",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const i2s0_m_ck_parents[] __initconst = {
+	"apll1_div1",
+	"apll2_div1"
+};
+
+static const char * const i2s1_m_ck_parents[] __initconst = {
+	"apll1_div2",
+	"apll2_div2"
+};
+
+static const char * const i2s2_m_ck_parents[] __initconst = {
+	"apll1_div3",
+	"apll2_div3"
+};
+
+static const char * const i2s3_m_ck_parents[] __initconst = {
+	"apll1_div4",
+	"apll2_div4"
+};
+
+static const char * const i2s3_b_ck_parents[] __initconst = {
+	"apll1_div5",
+	"apll2_div5"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
+	MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
+	/* CLK_CFG_5 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
+	MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
+	MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
+	/* CLK_CFG_12 */
+	MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
+	/* CLK_CFG_13 */
+	MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
+	MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
+
+	DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
+	DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
+	DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
+	DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
+
+	DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
+	DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
+	DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
+	DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
+	DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
+	DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
+
+	MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
+	MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
+	MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
+	MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
+	MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
+	GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
+	GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
+	GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
+	GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
+	GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
+	GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8173_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8173_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+
+#define MT8173_PLL_FMAX		(3000UL * MHZ)
+
+#define CON0_MT8173_RST_BAR	BIT(24)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
+			_tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8173_RST_BAR,			\
+		.fmax = MT8173_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
+	PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+	PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
new file mode 100644
index 0000000..4ad76ed
--- /dev/null
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8173_H
+#define _DT_BINDINGS_CLK_MT8173_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_CLKPH_MCK_O		1
+#define CLK_TOP_DPI			2
+#define CLK_TOP_USB_SYSPLL_125M		3
+#define CLK_TOP_HDMITX_DIG_CTS		4
+#define CLK_TOP_ARMCA7PLL_754M		5
+#define CLK_TOP_ARMCA7PLL_502M		6
+#define CLK_TOP_MAIN_H546M		7
+#define CLK_TOP_MAIN_H364M		8
+#define CLK_TOP_MAIN_H218P4M		9
+#define CLK_TOP_MAIN_H156M		10
+#define CLK_TOP_TVDPLL_445P5M		11
+#define CLK_TOP_TVDPLL_594M		12
+#define CLK_TOP_UNIV_624M		13
+#define CLK_TOP_UNIV_416M		14
+#define CLK_TOP_UNIV_249P6M		15
+#define CLK_TOP_UNIV_178P3M		16
+#define CLK_TOP_UNIV_48M		17
+#define CLK_TOP_CLKRTC_EXT		18
+#define CLK_TOP_CLKRTC_INT		19
+#define CLK_TOP_FPC			20
+#define CLK_TOP_HDMITXPLL_D2		21
+#define CLK_TOP_HDMITXPLL_D3		22
+#define CLK_TOP_ARMCA7PLL_D2		23
+#define CLK_TOP_ARMCA7PLL_D3		24
+#define CLK_TOP_APLL1			25
+#define CLK_TOP_APLL2			26
+#define CLK_TOP_DMPLL			27
+#define CLK_TOP_DMPLL_D2		28
+#define CLK_TOP_DMPLL_D4		29
+#define CLK_TOP_DMPLL_D8		30
+#define CLK_TOP_DMPLL_D16		31
+#define CLK_TOP_LVDSPLL_D2		32
+#define CLK_TOP_LVDSPLL_D4		33
+#define CLK_TOP_LVDSPLL_D8		34
+#define CLK_TOP_MMPLL			35
+#define CLK_TOP_MMPLL_D2		36
+#define CLK_TOP_MSDCPLL			37
+#define CLK_TOP_MSDCPLL_D2		38
+#define CLK_TOP_MSDCPLL_D4		39
+#define CLK_TOP_MSDCPLL2		40
+#define CLK_TOP_MSDCPLL2_D2		41
+#define CLK_TOP_MSDCPLL2_D4		42
+#define CLK_TOP_SYSPLL_D2		43
+#define CLK_TOP_SYSPLL1_D2		44
+#define CLK_TOP_SYSPLL1_D4		45
+#define CLK_TOP_SYSPLL1_D8		46
+#define CLK_TOP_SYSPLL1_D16		47
+#define CLK_TOP_SYSPLL_D3		48
+#define CLK_TOP_SYSPLL2_D2		49
+#define CLK_TOP_SYSPLL2_D4		50
+#define CLK_TOP_SYSPLL_D5		51
+#define CLK_TOP_SYSPLL3_D2		52
+#define CLK_TOP_SYSPLL3_D4		53
+#define CLK_TOP_SYSPLL_D7		54
+#define CLK_TOP_SYSPLL4_D2		55
+#define CLK_TOP_SYSPLL4_D4		56
+#define CLK_TOP_TVDPLL			57
+#define CLK_TOP_TVDPLL_D2		58
+#define CLK_TOP_TVDPLL_D4		59
+#define CLK_TOP_TVDPLL_D8		60
+#define CLK_TOP_TVDPLL_D16		61
+#define CLK_TOP_UNIVPLL_D2		62
+#define CLK_TOP_UNIVPLL1_D2		63
+#define CLK_TOP_UNIVPLL1_D4		64
+#define CLK_TOP_UNIVPLL1_D8		65
+#define CLK_TOP_UNIVPLL_D3		66
+#define CLK_TOP_UNIVPLL2_D2		67
+#define CLK_TOP_UNIVPLL2_D4		68
+#define CLK_TOP_UNIVPLL2_D8		69
+#define CLK_TOP_UNIVPLL_D5		70
+#define CLK_TOP_UNIVPLL3_D2		71
+#define CLK_TOP_UNIVPLL3_D4		72
+#define CLK_TOP_UNIVPLL3_D8		73
+#define CLK_TOP_UNIVPLL_D7		74
+#define CLK_TOP_UNIVPLL_D26		75
+#define CLK_TOP_UNIVPLL_D52		76
+#define CLK_TOP_VCODECPLL		77
+#define CLK_TOP_VCODECPLL_370P5		78
+#define CLK_TOP_VENCPLL			79
+#define CLK_TOP_VENCPLL_D2		80
+#define CLK_TOP_VENCPLL_D4		81
+#define CLK_TOP_AXI_SEL			82
+#define CLK_TOP_MEM_SEL			83
+#define CLK_TOP_DDRPHYCFG_SEL		84
+#define CLK_TOP_MM_SEL			85
+#define CLK_TOP_PWM_SEL			86
+#define CLK_TOP_VDEC_SEL		87
+#define CLK_TOP_VENC_SEL		88
+#define CLK_TOP_MFG_SEL			89
+#define CLK_TOP_CAMTG_SEL		90
+#define CLK_TOP_UART_SEL		91
+#define CLK_TOP_SPI_SEL			92
+#define CLK_TOP_USB20_SEL		93
+#define CLK_TOP_USB30_SEL		94
+#define CLK_TOP_MSDC50_0_H_SEL		95
+#define CLK_TOP_MSDC50_0_SEL		96
+#define CLK_TOP_MSDC30_1_SEL		97
+#define CLK_TOP_MSDC30_2_SEL		98
+#define CLK_TOP_MSDC30_3_SEL		99
+#define CLK_TOP_AUDIO_SEL		100
+#define CLK_TOP_AUD_INTBUS_SEL		101
+#define CLK_TOP_PMICSPI_SEL		102
+#define CLK_TOP_SCP_SEL			103
+#define CLK_TOP_ATB_SEL			104
+#define CLK_TOP_VENC_LT_SEL		105
+#define CLK_TOP_DPI0_SEL		106
+#define CLK_TOP_IRDA_SEL		107
+#define CLK_TOP_CCI400_SEL		108
+#define CLK_TOP_AUD_1_SEL		109
+#define CLK_TOP_AUD_2_SEL		110
+#define CLK_TOP_MEM_MFG_IN_SEL		111
+#define CLK_TOP_AXI_MFG_IN_SEL		112
+#define CLK_TOP_SCAM_SEL		113
+#define CLK_TOP_SPINFI_IFR_SEL		114
+#define CLK_TOP_HDMI_SEL		115
+#define CLK_TOP_DPILVDS_SEL		116
+#define CLK_TOP_MSDC50_2_H_SEL		117
+#define CLK_TOP_HDCP_SEL		118
+#define CLK_TOP_HDCP_24M_SEL		119
+#define CLK_TOP_RTC_SEL			120
+#define CLK_TOP_APLL1_DIV0		121
+#define CLK_TOP_APLL1_DIV1		122
+#define CLK_TOP_APLL1_DIV2		123
+#define CLK_TOP_APLL1_DIV3		124
+#define CLK_TOP_APLL1_DIV4		125
+#define CLK_TOP_APLL1_DIV5		126
+#define CLK_TOP_APLL2_DIV0		127
+#define CLK_TOP_APLL2_DIV1		128
+#define CLK_TOP_APLL2_DIV2		129
+#define CLK_TOP_APLL2_DIV3		130
+#define CLK_TOP_APLL2_DIV4		131
+#define CLK_TOP_APLL2_DIV5		132
+#define CLK_TOP_I2S0_M_SEL		133
+#define CLK_TOP_I2S1_M_SEL		134
+#define CLK_TOP_I2S2_M_SEL		135
+#define CLK_TOP_I2S3_M_SEL		136
+#define CLK_TOP_I2S3_B_SEL		137
+#define CLK_TOP_NR_CLK			138
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMCA15PLL	1
+#define CLK_APMIXED_ARMCA7PLL	2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_VENCPLL		7
+#define CLK_APMIXED_TVDPLL		8
+#define CLK_APMIXED_MPLL		9
+#define CLK_APMIXED_VCODECPLL		10
+#define CLK_APMIXED_APLL1		11
+#define CLK_APMIXED_APLL2		12
+#define CLK_APMIXED_LVDSPLL		13
+#define CLK_APMIXED_MSDCPLL2		14
+#define CLK_APMIXED_NR_CLK		15
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_DBGCLK		1
+#define CLK_INFRA_SMI			2
+#define CLK_INFRA_AUDIO			3
+#define CLK_INFRA_GCE			4
+#define CLK_INFRA_L2C_SRAM		5
+#define CLK_INFRA_M4U			6
+#define CLK_INFRA_CPUM			7
+#define CLK_INFRA_KP			8
+#define CLK_INFRA_CEC			9
+#define CLK_INFRA_PMICSPI		10
+#define CLK_INFRA_PMICWRAP		11
+#define CLK_INFRA_NR_CLK		12
+
+/* PERI_SYS */
+
+#define CLK_PERI_NFI			1
+#define CLK_PERI_THERM			2
+#define CLK_PERI_PWM1			3
+#define CLK_PERI_PWM2			4
+#define CLK_PERI_PWM3			5
+#define CLK_PERI_PWM4			6
+#define CLK_PERI_PWM5			7
+#define CLK_PERI_PWM6			8
+#define CLK_PERI_PWM7			9
+#define CLK_PERI_PWM			10
+#define CLK_PERI_USB0			11
+#define CLK_PERI_USB1			12
+#define CLK_PERI_AP_DMA			13
+#define CLK_PERI_MSDC30_0		14
+#define CLK_PERI_MSDC30_1		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_3		17
+#define CLK_PERI_NLI_ARB		18
+#define CLK_PERI_IRDA			19
+#define CLK_PERI_UART0			20
+#define CLK_PERI_UART1			21
+#define CLK_PERI_UART2			22
+#define CLK_PERI_UART3			23
+#define CLK_PERI_I2C0			24
+#define CLK_PERI_I2C1			25
+#define CLK_PERI_I2C2			26
+#define CLK_PERI_I2C3			27
+#define CLK_PERI_I2C4			28
+#define CLK_PERI_AUXADC			29
+#define CLK_PERI_SPI0			30
+#define CLK_PERI_I2C5			31
+#define CLK_PERI_NFIECC			32
+#define CLK_PERI_SPI			33
+#define CLK_PERI_IRRX			34
+#define CLK_PERI_I2C6			35
+#define CLK_PERI_UART0_SEL		36
+#define CLK_PERI_UART1_SEL		37
+#define CLK_PERI_UART2_SEL		38
+#define CLK_PERI_UART3_SEL		39
+#define CLK_PERI_NR_CLK			40
+
+#endif /* _DT_BINDINGS_CLK_MT8173_H */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 0000000..9464b37
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST        0
+#define MT8173_INFRA_DRAMC0_A0_RST      1
+#define MT8173_INFRA_APCIRQ_EINT_RST    3
+#define MT8173_INFRA_APXGPT_RST         4
+#define MT8173_INFRA_SCPSYS_RST         5
+#define MT8173_INFRA_KP_RST             6
+#define MT8173_INFRA_PMIC_WRAP_RST      7
+#define MT8173_INFRA_MPIP_RST           8
+#define MT8173_INFRA_CEC_RST            9
+#define MT8173_INFRA_EMI_RST            32
+#define MT8173_INFRA_DRAMC0_RST         34
+#define MT8173_INFRA_APMIXEDSYS_RST     35
+#define MT8173_INFRA_MIPI_DSI_RST       36
+#define MT8173_INFRA_TRNG_RST           37
+#define MT8173_INFRA_SYSIRQ_RST         38
+#define MT8173_INFRA_MIPI_CSI_RST       39
+#define MT8173_INFRA_GCE_FAXI_RST       40
+#define MT8173_INFRA_MMIOMMURST         47
+
+
+/*  PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST        0
+#define MT8173_PERI_UART1_SW_RST        1
+#define MT8173_PERI_UART2_SW_RST        2
+#define MT8173_PERI_UART3_SW_RST        3
+#define MT8173_PERI_IRRX_SW_RST         4
+#define MT8173_PERI_PWM_SW_RST          8
+#define MT8173_PERI_AUXADC_SW_RST       10
+#define MT8173_PERI_DMA_SW_RST          11
+#define MT8173_PERI_I2C6_SW_RST         13
+#define MT8173_PERI_NFI_SW_RST          14
+#define MT8173_PERI_THERM_SW_RST        16
+#define MT8173_PERI_MSDC2_SW_RST        17
+#define MT8173_PERI_MSDC3_SW_RST        18
+#define MT8173_PERI_MSDC0_SW_RST        19
+#define MT8173_PERI_MSDC1_SW_RST        20
+#define MT8173_PERI_I2C0_SW_RST         22
+#define MT8173_PERI_I2C1_SW_RST         23
+#define MT8173_PERI_I2C2_SW_RST         24
+#define MT8173_PERI_I2C3_SW_RST         25
+#define MT8173_PERI_I2C4_SW_RST         26
+#define MT8173_PERI_HDMI_SW_RST         29
+#define MT8173_PERI_SPI0_SW_RST         33
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:35:40 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:40 +0200
Subject: [PATCH 3/6] clk: mediatek: Add reset controller support
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-4-git-send-email-s.hauer@pengutronix.de>

The pericfg and infracfg units also provide reset lines to several
other SoC internal units. This adds a function which can be called
from the pericfg and infracfg initialization functions which will
register the reset controller using reset_controller_register. The
reset controller will provide support for resetting the units
connected to the pericfg and infracfg controller. The units resetted
by this controller can use the standard reset device tree binding
to gain access to the reset lines.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 drivers/clk/mediatek/Makefile  |  1 +
 drivers/clk/mediatek/clk-mtk.h | 10 +++++
 drivers/clk/mediatek/reset.c   | 97 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/clk/mediatek/reset.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index c384e97..0b6f1c3 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1 +1,2 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 694fc39..61035b9 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -156,4 +156,14 @@ void __init mtk_clk_register_plls(struct device_node *node,
 		const struct mtk_pll_data *plls, int num_plls,
 		struct clk_onecell_data *clk_data);
 
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+}
+#endif
+
 #endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
new file mode 100644
index 0000000..9e9fe4b
--- /dev/null
+++ b/drivers/clk/mediatek/reset.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ *
+ * 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.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+struct mtk_reset {
+	struct regmap *regmap;
+	int regofs;
+	struct reset_controller_dev rcdev;
+};
+
+static int mtk_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), ~0);
+}
+
+static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), 0);
+}
+
+static int mtk_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	ret = mtk_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return mtk_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_reset_ops = {
+	.assert = mtk_reset_assert,
+	.deassert = mtk_reset_deassert,
+	.reset = mtk_reset,
+};
+
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+	struct mtk_reset *data;
+	int ret;
+	struct regmap *regmap;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
+				PTR_ERR(regmap));
+		return;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return;
+
+	data->regmap = regmap;
+	data->regofs = regofs;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = num_regs * 32;
+	data->rcdev.ops = &mtk_reset_ops;
+	data->rcdev.of_node = np;
+
+	ret = reset_controller_register(&data->rcdev);
+	if (ret) {
+		pr_err("could not register reset controller: %d\n", ret);
+		kfree(data);
+		return;
+	}
+}
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:35:39 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:39 +0200
Subject: [PATCH 2/6] clk: mediatek: Add initial common clock support for
 Mediatek SoCs.
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-3-git-send-email-s.hauer@pengutronix.de>

From: James Liao <jamesjj.liao at mediatek.com>

This patch adds common clock support for Mediatek SoCs, including plls,
muxes and clock gates.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/Makefile            |   1 +
 drivers/clk/mediatek/Makefile   |   1 +
 drivers/clk/mediatek/clk-gate.c | 137 +++++++++++++++++
 drivers/clk/mediatek/clk-gate.h |  49 ++++++
 drivers/clk/mediatek/clk-mtk.c  | 220 ++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h  | 159 +++++++++++++++++++
 drivers/clk/mediatek/clk-pll.c  | 332 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 899 insertions(+)
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-gate.c
 create mode 100644 drivers/clk/mediatek/clk-gate.h
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h
 create mode 100644 drivers/clk/mediatek/clk-pll.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d478ceb..6d97203 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
+obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000..c384e97
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1 @@
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 0000000..9d77ee3
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val == 0;
+}
+
+static int mtk_cg_bit_is_set(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static void mtk_cg_set_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+}
+
+static void mtk_cg_clr_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+}
+
+static int mtk_cg_enable(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+}
+
+static int mtk_cg_enable_inv(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+}
+
+const struct clk_ops mtk_clk_gate_ops_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable,
+	.disable	= mtk_cg_disable,
+};
+
+const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv,
+	.disable	= mtk_cg_disable_inv,
+};
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops)
+{
+	struct mtk_clk_gate *cg;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = ops;
+
+	cg->regmap = regmap;
+	cg->set_ofs = set_ofs;
+	cg->clr_ofs = clr_ofs;
+	cg->sta_ofs = sta_ofs;
+	cg->bit = bit;
+
+	cg->hw.init = &init;
+
+	clk = clk_register(NULL, &cg->hw);
+	if (IS_ERR(clk))
+		kfree(cg);
+
+	return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 0000000..6b6780b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#ifndef __DRV_CLK_GATE_H
+#define __DRV_CLK_GATE_H
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	int		set_ofs;
+	int		clr_ofs;
+	int		sta_ofs;
+	u8		bit;
+};
+
+static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_gate, hw);
+}
+
+extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 0000000..18444ae
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+{
+	int i;
+	struct clk_onecell_data *clk_data;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return NULL;
+
+	clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_out;
+
+	clk_data->clk_num = clk_num;
+
+	for (i = 0; i < clk_num; i++)
+		clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+	return clk_data;
+err_out:
+	kfree(clk_data);
+
+	return NULL;
+}
+
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_fixed_factor *ff = &clks[i];
+
+		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+				CLK_SET_RATE_PARENT, ff->mult, ff->div);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					ff->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[ff->id] = clk;
+	}
+}
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	if (!clk_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+				PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_gate *gate = &clks[i];
+
+		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+				regmap,
+				gate->regs->set_ofs,
+				gate->regs->clr_ofs,
+				gate->regs->sta_ofs,
+				gate->shift, gate->ops);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					gate->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[gate->id] = clk;
+	}
+
+	return 0;
+}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
+	const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
+	const char * const *parent_names;
+	const char *parent;
+	int num_parents;
+	int ret;
+
+	if (mc->mux_shift >= 0) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = base + mc->mux_reg;
+		mux->mask = BIT(mc->mux_width) - 1;
+		mux->shift = mc->mux_shift;
+		mux->lock = lock;
+
+		mux_hw = &mux->hw;
+		mux_ops = &clk_mux_ops;
+
+		parent_names = mc->parent_names;
+		num_parents = mc->num_parents;
+	} else {
+		parent = mc->parent;
+		parent_names = &parent;
+		num_parents = 1;
+	}
+
+	if (mc->gate_shift >= 0) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		gate->reg = base + mc->gate_reg;
+		gate->bit_idx = mc->gate_shift;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = lock;
+
+		gate_hw = &gate->hw;
+		gate_ops = &clk_gate_ops;
+	}
+
+	if (mc->divider_shift >= 0) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		div->reg = base + mc->divider_reg;
+		div->shift = mc->divider_shift;
+		div->width = mc->divider_width;
+		div->lock = lock;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
+		mux_hw, mux_ops,
+		div_hw, div_ops,
+		gate_hw, gate_ops,
+		mc->flags);
+
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(mux);
+	}
+
+	return clk;
+err_out:
+	kfree(mux);
+
+	return ERR_PTR(ret);
+}
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_composite *mc = &mcs[i];
+
+		clk = mtk_clk_register_composite(mc, base, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					mc->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mc->id] = clk;
+	}
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 0000000..694fc39
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#ifndef __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define MAX_MUX_GATE_BIT	31
+#define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
+
+#define MHZ (1000 * 1000)
+
+struct mtk_fixed_factor {
+	int id;
+	const char *name;
+	const char *parent_name;
+	int mult;
+	int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.mult = _mult,				\
+		.div = _div,				\
+	}
+
+extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct mtk_composite {
+	int id;
+	const char *name;
+	const char * const * parent_names;
+	const char *parent;
+	unsigned flags;
+
+	uint32_t mux_reg;
+	uint32_t divider_reg;
+	uint32_t gate_reg;
+
+	signed char mux_shift;
+	signed char mux_width;
+	signed char gate_shift;
+
+	signed char divider_shift;
+	signed char divider_width;
+
+	signed char num_parents;
+};
+
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_reg = _reg,					\
+		.gate_shift = _gate,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = -1,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+		.id = _id,						\
+		.parent = _parent,					\
+		.name = _name,						\
+		.divider_reg = _div_reg,				\
+		.divider_shift = _div_shift,				\
+		.divider_width = _div_width,				\
+		.gate_reg = _gate_reg,					\
+		.gate_shift = _gate_shift,				\
+		.mux_shift = -1,					\
+		.flags = 0,						\
+	}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock);
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data);
+
+struct mtk_gate_regs {
+	u32 sta_ofs;
+	u32 clr_ofs;
+	u32 set_ofs;
+};
+
+struct mtk_gate {
+	int id;
+	const char *name;
+	const char *parent_name;
+	const struct mtk_gate_regs *regs;
+	int shift;
+	const struct clk_ops *ops;
+};
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
+
+#define HAVE_RST_BAR	BIT(0)
+
+struct mtk_pll_data {
+	int id;
+	const char *name;
+	uint32_t reg;
+	uint32_t pwr_reg;
+	uint32_t en_mask;
+	uint32_t pd_reg;
+	uint32_t tuner_reg;
+	int pd_shift;
+	unsigned int flags;
+	const struct clk_ops *ops;
+	u32 rst_bar_mask;
+	unsigned long fmax;
+	int pcwbits;
+	uint32_t pcw_reg;
+	int pcw_shift;
+};
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls,
+		struct clk_onecell_data *clk_data);
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 0000000..66154ca
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+
+#define REG_CON0		0
+#define REG_CON1		4
+
+#define CON0_BASE_EN		BIT(0)
+#define CON0_PWR_ON		BIT(0)
+#define CON0_ISO_EN		BIT(1)
+#define CON0_PCW_CHG		BIT(31)
+
+#define AUDPLL_TUNER_EN		BIT(31)
+
+#define POSTDIV_MASK		0x7
+#define INTEGER_BITS		7
+
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base_addr;
+	void __iomem	*pd_addr;
+	void __iomem	*pwr_addr;
+	void __iomem	*tuner_addr;
+	void __iomem	*pcw_addr;
+	const struct mtk_pll_data *data;
+};
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+static int mtk_pll_is_prepared(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
+}
+
+static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
+		u32 pcw, int postdiv)
+{
+	int pcwbits = pll->data->pcwbits;
+	int pcwfbits;
+	u64 vco;
+	u8 c = 0;
+
+	/* The fractional part of the PLL divider. */
+	pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+
+	vco = (u64)fin * pcw;
+
+	if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+		c = 1;
+
+	vco >>= pcwfbits;
+
+	if (c)
+		vco++;
+
+	return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+		int postdiv)
+{
+	u32 con1, pd, val;
+	int pll_en;
+
+	/* set postdiv */
+	pd = readl(pll->pd_addr);
+	pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
+	pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+	writel(pd, pll->pd_addr);
+
+	pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+
+	/* set pcw */
+	val = readl(pll->pcw_addr);
+
+	val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
+			pll->data->pcw_shift);
+	val |= pcw << pll->data->pcw_shift;
+	writel(val, pll->pcw_addr);
+
+	con1 = readl(pll->base_addr + REG_CON1);
+
+	if (pll_en)
+		con1 |= CON0_PCW_CHG;
+
+	writel(con1, pll->base_addr + REG_CON1);
+	if (pll->tuner_addr)
+		writel(con1 + 1, pll->tuner_addr);
+
+	if (pll_en)
+		udelay(20);
+}
+
+/*
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @pll:	The pll
+ * @pcw:	The pcw value (output)
+ * @postdiv:	The post divider (output)
+ * @freq:	The desired target frequency
+ * @fin:	The input frequency
+ *
+ */
+static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+		u32 freq, u32 fin)
+{
+	unsigned long fmin = 1000 * MHZ;
+	u64 _pcw;
+	u32 val;
+
+	if (freq > pll->data->fmax)
+		freq = pll->data->fmax;
+
+	for (val = 0; val < 4; val++) {
+		*postdiv = 1 << val;
+		if (freq * *postdiv >= fmin)
+			break;
+	}
+
+	/* _pcw = freq * postdiv / fin * 2^pcwfbits */
+	_pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+	do_div(_pcw, fin);
+
+	*pcw = (u32)_pcw;
+}
+
+static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	u32 postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+	mtk_pll_set_rate_regs(pll, pcw, postdiv);
+
+	return 0;
+}
+
+static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 postdiv;
+	u32 pcw;
+
+	postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
+	postdiv = 1 << postdiv;
+
+	pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
+	pcw &= GENMASK(pll->data->pcwbits - 1, 0);
+
+	return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
+}
+
+static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	int postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
+
+	return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
+}
+
+static int mtk_pll_prepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	r = readl(pll->pwr_addr) | CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->base_addr + REG_CON0);
+	r |= pll->data->en_mask;
+	writel(r, pll->base_addr + REG_CON0);
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	udelay(20);
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r |= pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	return 0;
+}
+
+static void mtk_pll_unprepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r &= ~pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	r = readl(pll->base_addr + REG_CON0);
+	r &= ~CON0_BASE_EN;
+	writel(r, pll->base_addr + REG_CON0);
+
+	r = readl(pll->pwr_addr) | CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+
+	r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+}
+
+static const struct clk_ops mtk_pll_ops = {
+	.is_prepared	= mtk_pll_is_prepared,
+	.prepare	= mtk_pll_prepare,
+	.unprepare	= mtk_pll_unprepare,
+	.recalc_rate	= mtk_pll_recalc_rate,
+	.round_rate	= mtk_pll_round_rate,
+	.set_rate	= mtk_pll_set_rate,
+};
+
+static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
+		void __iomem *base)
+{
+	struct mtk_clk_pll *pll;
+	struct clk_init_data init;
+	struct clk *clk;
+	const char *parent_name = "clk26m";
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	pll->base_addr = base + data->reg;
+	pll->pwr_addr = base + data->pwr_reg;
+	pll->pd_addr = base + data->pd_reg;
+	pll->pcw_addr = base + data->pcw_reg;
+	if (data->tuner_reg)
+		pll->tuner_addr = base + data->tuner_reg;
+	pll->hw.init = &init;
+	pll->data = data;
+
+	init.name = data->name;
+	init.ops = &mtk_pll_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
+{
+	void __iomem *base;
+	int r, i;
+	struct clk *clk;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num_plls; i++) {
+		const struct mtk_pll_data *pll = &plls[i];
+
+		clk = mtk_clk_register_pll(pll, base);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					pll->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[pll->id] = clk;
+	}
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:35:38 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:35:38 +0200
Subject: [PATCH 1/6] clk: make strings in parent name arrays const
In-Reply-To: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429778143-2074-2-git-send-email-s.hauer@pengutronix.de>

The clk functions and structs declare the parent_name arrays as
'const char **parent_names' which means the parent name strings
are const, but the array itself is not. Use
'const char * const * parent_names' instead which also makes
the array const. This allows us to put the parent_name arrays into
the __initconst section.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Tested-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/clk-composite.c  | 2 +-
 drivers/clk/clk-mux.c        | 4 ++--
 include/linux/clk-provider.h | 8 ++++----
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 956b7e5..077f4c714 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
 }
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-			const char **parent_names, int num_parents,
+			const char * const *parent_names, int num_parents,
 			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 			struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 69a094c..1fa2a8d 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -114,7 +114,7 @@ const struct clk_ops clk_mux_ro_ops = {
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
@@ -166,7 +166,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock)
 {
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..410684d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -209,7 +209,7 @@ struct clk_ops {
 struct clk_init_data {
 	const char		*name;
 	const struct clk_ops	*ops;
-	const char		**parent_names;
+	const char		* const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 };
@@ -426,12 +426,12 @@ extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
@@ -518,7 +518,7 @@ struct clk_composite {
 };
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-		const char **parent_names, int num_parents,
+		const char * const *parent_names, int num_parents,
 		struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 		struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 		struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
-- 
2.1.4



From u.kleine-koenig at pengutronix.de  Thu Apr 23 01:48:17 2015
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Thu, 23 Apr 2015 10:48:17 +0200
Subject: [PATCH 1/6] clk: make strings in parent name arrays const
In-Reply-To: <1429778143-2074-2-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
 <1429778143-2074-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150423084817.GB19431@pengutronix.de>

Halli,

On Thu, Apr 23, 2015 at 10:35:38AM +0200, Sascha Hauer wrote:
> The clk functions and structs declare the parent_name arrays as
> 'const char **parent_names' which means the parent name strings
> are const, but the array itself is not. Use
> 'const char * const * parent_names' instead which also makes
> the array const. This allows us to put the parent_name arrays into
> the __initconst section.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Tested-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Acked-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From s.hauer at pengutronix.de  Thu Apr 23 01:51:02 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:51:02 +0200
Subject: tty: serial: 8250_mtk: Add support for second clock
Message-ID: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>


The following changes since commit 39a8804455fb23f09157341d3ba7db6d7ae6ee76:

  Linux 4.0 (2015-04-12 15:12:50 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/sha/linux-2.6.git tags/v4.0-mtk-uart-clk

for you to fetch changes up to 91bb93e93bf0916f9ebf571e8ab7cb671322ebc8:

  tty: serial: 8250_mtk: Add support for bus clock (2015-04-23 10:36:04 +0200)

----------------------------------------------------------------
This series adds support for the second clock on the Mediatek UART.
This is necessary for SoCs needing a bus clock to be enabled before
the UART can be accessed.

----------------------------------------------------------------
Sascha Hauer (4):
      tty: serial: 8250_mtk: Use devm_clk_get
      tty: serial: 8250_mtk: remove unnecessary test
      tty: serial: 8250_mtk: use pm_runtime callbacks for enabling
      tty: serial: 8250_mtk: Add support for bus clock

 .../devicetree/bindings/serial/mtk-uart.txt        |  9 ++-
 drivers/tty/serial/8250/8250_mtk.c                 | 92 ++++++++++++----------
 2 files changed, 57 insertions(+), 44 deletions(-)


From s.hauer at pengutronix.de  Thu Apr 23 01:51:04 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:51:04 +0200
Subject: [PATCH 2/4] tty: serial: 8250_mtk: remove unnecessary test
In-Reply-To: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429779066-21406-3-git-send-email-s.hauer@pengutronix.de>

When the driver has probed successfully the clk pointer is always valid,
so no need to test for it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index c6901dc..bcfaa8dc 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -212,9 +212,7 @@ static int mtk8250_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 
 	serial8250_unregister_port(data->line);
-	if (!IS_ERR(data->uart_clk)) {
-		clk_disable_unprepare(data->uart_clk);
-	}
+	clk_disable_unprepare(data->uart_clk);
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
@@ -246,8 +244,7 @@ static int mtk8250_runtime_suspend(struct device *dev)
 {
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
-	if (!IS_ERR(data->uart_clk))
-		clk_disable_unprepare(data->uart_clk);
+	clk_disable_unprepare(data->uart_clk);
 
 	return 0;
 }
@@ -256,8 +253,7 @@ static int mtk8250_runtime_resume(struct device *dev)
 {
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
-	if (!IS_ERR(data->uart_clk))
-		clk_prepare_enable(data->uart_clk);
+	clk_prepare_enable(data->uart_clk);
 
 	return 0;
 }
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:51:05 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:51:05 +0200
Subject: [PATCH 3/4] tty: serial: 8250_mtk: use pm_runtime callbacks for
 enabling
In-Reply-To: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429779066-21406-4-git-send-email-s.hauer@pengutronix.de>

The pm_runtime callbacks already enable and disable the device.
Use them in probe() and remove() instead of duplicating the
code. This allows us to concentrate more code for enabling/disabling
the UART in a single place.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 69 ++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index bcfaa8dc..2f28bd0 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -115,6 +115,29 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
 		tty_termios_encode_baud_rate(termios, baud, baud);
 }
 
+static int mtk8250_runtime_suspend(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(data->uart_clk);
+
+	return 0;
+}
+
+static int mtk8250_runtime_resume(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+	int err;
+
+	err = clk_prepare_enable(data->uart_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable clock\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static void
 mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 {
@@ -130,19 +153,12 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
-	int err;
-
 	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(data->uart_clk)) {
 		dev_warn(&pdev->dev, "Can't get uart clock\n");
 		return PTR_ERR(data->uart_clk);
 	}
 
-	err = clk_prepare_enable(data->uart_clk);
-	if (err) {
-		dev_warn(&pdev->dev, "Can't prepare clock\n");
-		return err;
-	}
 	p->uartclk = clk_get_rate(data->uart_clk);
 
 	return 0;
@@ -193,14 +209,18 @@ static int mtk8250_probe(struct platform_device *pdev)
 	writel(0x0, uart.port.membase +
 			(MTK_UART_RATE_FIX << uart.port.regshift));
 
-	data->line = serial8250_register_8250_port(&uart);
-	if (data->line < 0)
-		return data->line;
-
 	platform_set_drvdata(pdev, data);
 
-	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		err = mtk8250_runtime_resume(&pdev->dev);
+		if (err)
+			return err;
+	}
+
+	data->line = serial8250_register_8250_port(&uart);
+	if (data->line < 0)
+		return data->line;
 
 	return 0;
 }
@@ -212,10 +232,13 @@ static int mtk8250_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 
 	serial8250_unregister_port(data->line);
-	clk_disable_unprepare(data->uart_clk);
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
+
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		mtk8250_runtime_suspend(&pdev->dev);
+
 	return 0;
 }
 
@@ -239,26 +262,6 @@ static int mtk8250_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-#ifdef CONFIG_PM
-static int mtk8250_runtime_suspend(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	clk_disable_unprepare(data->uart_clk);
-
-	return 0;
-}
-
-static int mtk8250_runtime_resume(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	clk_prepare_enable(data->uart_clk);
-
-	return 0;
-}
-#endif
-
 static const struct dev_pm_ops mtk8250_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume)
 	SET_RUNTIME_PM_OPS(mtk8250_runtime_suspend, mtk8250_runtime_resume,
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:51:06 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:51:06 +0200
Subject: [PATCH 4/4] tty: serial: 8250_mtk: Add support for bus clock
In-Reply-To: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429779066-21406-5-git-send-email-s.hauer@pengutronix.de>

The mtk 8250 needs two clocks, one for providing the baudrate and
one that needs to be enabled for register accesses. The latter has
not been supported, this patch adds support for it. It is optional
for now since not all SoCs provide a bus clock.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 Documentation/devicetree/bindings/serial/mtk-uart.txt |  9 +++++++--
 drivers/tty/serial/8250/8250_mtk.c                    | 14 +++++++++++++-
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 4415226..369b5c3 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -14,7 +14,11 @@ Required properties:
 
 - interrupts: A single interrupt specifier.
 
-- clocks: Clock driving the hardware.
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names:
+  - "baud": The clock the baudrate is derived from
+  - "bus": The bus clock for register accesses (optional)
 
 Example:
 
@@ -22,5 +26,6 @@ Example:
 		compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
 		reg = <0x11006000 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&uart_clk>, <&bus_clk>;
+		clock-names = "baud", "bus";
 	};
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 2f28bd0..20c27f0 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -34,6 +34,7 @@
 struct mtk8250_data {
 	int			line;
 	struct clk		*uart_clk;
+	struct clk		*bus_clk;
 };
 
 static void
@@ -120,6 +121,7 @@ static int mtk8250_runtime_suspend(struct device *dev)
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
 	clk_disable_unprepare(data->uart_clk);
+	clk_disable_unprepare(data->bus_clk);
 
 	return 0;
 }
@@ -135,6 +137,12 @@ static int mtk8250_runtime_resume(struct device *dev)
 		return err;
 	}
 
+	err = clk_prepare_enable(data->bus_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable bus clock\n");
+		return err;
+	}
+
 	return 0;
 }
 
@@ -153,7 +161,7 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
-	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
+	data->uart_clk = devm_clk_get(&pdev->dev, "baud");
 	if (IS_ERR(data->uart_clk)) {
 		dev_warn(&pdev->dev, "Can't get uart clock\n");
 		return PTR_ERR(data->uart_clk);
@@ -161,6 +169,10 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 
 	p->uartclk = clk_get_rate(data->uart_clk);
 
+	data->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(data->bus_clk))
+		data->bus_clk = NULL;
+
 	return 0;
 }
 
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 01:51:03 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 10:51:03 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>

Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
which is the correct function when a struct device * is available. Also
since it's a devm function we can drop the calls to clk_put(). While at
it also fix a wrong debug message.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 7a11fac..c6901dc 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
 	int err;
-	struct device_node *np = pdev->dev.of_node;
 
-	data->uart_clk = of_clk_get(np, 0);
+	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(data->uart_clk)) {
-		dev_warn(&pdev->dev, "Can't get timer clock\n");
+		dev_warn(&pdev->dev, "Can't get uart clock\n");
 		return PTR_ERR(data->uart_clk);
 	}
 
 	err = clk_prepare_enable(data->uart_clk);
 	if (err) {
 		dev_warn(&pdev->dev, "Can't prepare clock\n");
-		clk_put(data->uart_clk);
 		return err;
 	}
 	p->uartclk = clk_get_rate(data->uart_clk);
@@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
 	serial8250_unregister_port(data->line);
 	if (!IS_ERR(data->uart_clk)) {
 		clk_disable_unprepare(data->uart_clk);
-		clk_put(data->uart_clk);
 	}
 
 	pm_runtime_disable(&pdev->dev);
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 02:21:13 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:21:13 +0200
Subject: [PATCH 2/4] ARM: dts: mt8135: Add pmic wrapper nodes
In-Reply-To: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429780875-29096-3-git-send-email-s.hauer@pengutronix.de>

This adds the pmic wrapper node to the MediaTek MT8135 dtsi file.

This unit is used to access the PMIC on MediaTek boards.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boot/dts/mt8135.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index b4017e2..b0f20fc 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -15,6 +15,7 @@
 #include <dt-bindings/clock/mt8135-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset-controller/mt8135-resets.h>
 #include "skeleton64.dtsi"
 
 / {
@@ -127,6 +128,19 @@
 			reg = <0 0x10003000 0 0x1000>;
 		};
 
+		pwrap: pwrap at 1000f000 {
+			compatible = "mediatek,mt8135-pwrap";
+			reg = <0 0x1000f000 0 0x1000>,
+				<0 0x11017000 0 0x1000>;
+			reg-names = "pwrap", "pwrap-bridge";
+			interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
+					<&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+			reset-names = "pwrap", "pwrap-bridge";
+			clocks = <&clk26m>, <&clk26m>;
+			clock-names = "spi", "wrap";
+		};
+
 		timer: timer at 10008000 {
 			compatible = "mediatek,mt8135-timer",
 					"mediatek,mt6577-timer";
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 02:21:12 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:21:12 +0200
Subject: [PATCH 1/4] ARM: dts: mediatek: Enable clock support for Mediatek
 MT8135.
In-Reply-To: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429780875-29096-2-git-send-email-s.hauer@pengutronix.de>

From: James Liao <jamesjj.liao at mediatek.com>

This patch adds MT8135 clock controllers into device tree.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boot/dts/mt8135.dtsi | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index a161e99..b4017e2 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/clock/mt8135-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "skeleton64.dtsi"
@@ -93,6 +94,11 @@
 			#clock-cells = <0>;
 		};
 
+		clk26m: clk26m {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+		};
 	};
 
 	soc {
@@ -101,6 +107,26 @@
 		compatible = "simple-bus";
 		ranges;
 
+		topckgen: topckgen at 10000000 {
+			compatible = "mediatek,mt8135-topckgen";
+			reg = <0 0x10000000 0 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		infracfg: infracfg at 10001000 {
+			#reset-cells = <1>;
+			#clock-cells = <1>;
+			compatible = "mediatek,mt8135-infracfg", "syscon";
+			reg = <0 0x10001000 0 0x1000>;
+		};
+
+		pericfg: pericfg at 10003000 {
+			#reset-cells = <1>;
+			#clock-cells = <1>;
+			compatible = "mediatek,mt8135-pericfg", "syscon";
+			reg = <0 0x10003000 0 0x1000>;
+		};
+
 		timer: timer at 10008000 {
 			compatible = "mediatek,mt8135-timer",
 					"mediatek,mt6577-timer";
@@ -119,6 +145,12 @@
 			reg = <0 0x10200030 0 0x1c>;
 		};
 
+		apmixedsys: apmixedsys at 10209000 {
+			compatible = "mediatek,mt8135-apmixedsys";
+			reg = <0 0x10209000 0 0x1000>;
+			#clock-cells = <1>;
+		};
+
 		gic: interrupt-controller at 10211000 {
 			compatible = "arm,cortex-a15-gic";
 			interrupt-controller;
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 02:21:11 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:21:11 +0200
Subject: Mediatek MT8135 dts updates
Message-ID: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>

This series contains the Mediatek MT8135 dts updates for the clock
support and UART support. This needs these two series:

[PATCH v12] clk: Add common clock support for Mediatek MT8135 and MT8173
tty: serial: 8250_mtk: Add support for second clock

Also this adds the PMIC wrapper nodes to the dtsi file and PMIC node to
the mt8135-evbp1 board. Support for the PMIC wrapper was merged during
the v4.1 merge window.

This series is meant for testing the new features, not (yet) for inclusion.

----------------------------------------------------------------

The following changes since commit 39a8804455fb23f09157341d3ba7db6d7ae6ee76:

  Linux 4.0 (2015-04-12 15:12:50 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/sha/linux-2.6.git tags/v4.0-mtk-arm-dts

for you to fetch changes up to 5fcd75a6aeded756c24d9581f49e0859b85fb3a0:

  ARM: dts: mediatek mt8135: Use real UART clocks (2015-04-23 11:02:27 +0200)

----------------------------------------------------------------

James Liao (1):
      ARM: dts: mediatek: Enable clock support for Mediatek MT8135.

Sascha Hauer (3):
      ARM: dts: mt8135: Add pmic wrapper nodes
      ARM: dts: mt8135-evbp1: Add PMIC support
      ARM: dts: mediatek mt8135: Use real UART clocks

 arch/arm/boot/dts/mt8135-evbp1.dts | 193 +++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/mt8135.dtsi      |  58 ++++++++++-
 2 files changed, 247 insertions(+), 4 deletions(-)


From s.hauer at pengutronix.de  Thu Apr 23 02:21:15 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:21:15 +0200
Subject: [PATCH 4/4] ARM: dts: mediatek mt8135: Use real UART clocks
In-Reply-To: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429780875-29096-5-git-send-email-s.hauer@pengutronix.de>

We used to provide dummy clocks for the UART. Now that we have
common clock support we can provide the real clocks to the UART.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boot/dts/mt8135.dtsi | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index b0f20fc..4d1ddd9 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -180,7 +180,8 @@
 			compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart";
 			reg = <0 0x11006000 0 0x400>;
 			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-			clocks = <&uart_clk>;
+			clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
+			clock-names = "baud", "bus";
 			status = "disabled";
 		};
 
@@ -188,7 +189,8 @@
 			compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart";
 			reg = <0 0x11007000 0 0x400>;
 			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
-			clocks = <&uart_clk>;
+			clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
+			clock-names = "baud", "bus";
 			status = "disabled";
 		};
 
@@ -196,7 +198,8 @@
 			compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart";
 			reg = <0 0x11008000 0 0x400>;
 			interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
-			clocks = <&uart_clk>;
+			clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
+			clock-names = "baud", "bus";
 			status = "disabled";
 		};
 
@@ -204,7 +207,8 @@
 			compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart";
 			reg = <0 0x11009000 0 0x400>;
 			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
-			clocks = <&uart_clk>;
+			clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
+			clock-names = "baud", "bus";
 			status = "disabled";
 		};
 
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 02:21:14 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:21:14 +0200
Subject: [PATCH 3/4] ARM: dts: mt8135-evbp1: Add PMIC support
In-Reply-To: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1429780875-29096-4-git-send-email-s.hauer@pengutronix.de>

The MT8135 eval board contains a MT6397 PMIC. This adds the
corresponding device node to the dts file.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boot/dts/mt8135-evbp1.dts | 193 +++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)

diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
index 3667738..357a91f 100644
--- a/arch/arm/boot/dts/mt8135-evbp1.dts
+++ b/arch/arm/boot/dts/mt8135-evbp1.dts
@@ -24,6 +24,199 @@
 	};
 };
 
+&pwrap {
+	pmic: mt6397 {
+		compatible = "mediatek,mt6397";
+
+		mt6397regulator: mt6397regulator {
+			compatible = "mediatek,mt6397-regulator";
+
+			mt6397_vpca15_reg: buck_vpca15 {
+				regulator-compatible = "buck_vpca15";
+				regulator-name = "vpca15";
+				regulator-min-microvolt = < 850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vpca7_reg: buck_vpca7 {
+				regulator-compatible = "buck_vpca7";
+				regulator-name = "vpca7";
+				regulator-min-microvolt = < 850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vsramca15_reg: buck_vsramca15 {
+				regulator-compatible = "buck_vsramca15";
+				regulator-name = "vsramca15";
+				regulator-min-microvolt = < 850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vsramca7_reg: buck_vsramca7 {
+				regulator-compatible = "buck_vsramca7";
+				regulator-name = "vsramca7";
+				regulator-min-microvolt = < 850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vcore_reg: buck_vcore {
+				regulator-compatible = "buck_vcore";
+				regulator-name = "vcore";
+				regulator-min-microvolt = < 850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vgpu_reg: buck_vgpu {
+				regulator-compatible = "buck_vgpu";
+				regulator-name = "vgpu";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-enable-ramp-delay = <115>;
+			};
+
+			mt6397_vdrm_reg: buck_vdrm {
+				regulator-compatible = "buck_vdrm";
+				regulator-name = "vdrm";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vio18_reg: buck_vio18 {
+				regulator-compatible = "buck_vio18";
+				regulator-name = "vio18";
+				regulator-min-microvolt = <1620000>;
+				regulator-max-microvolt = <1980000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vtcxo_reg: ldo_vtcxo {
+				regulator-compatible = "ldo_vtcxo";
+				regulator-name = "vtcxo";
+				regulator-always-on;
+			};
+
+			mt6397_va28_reg: ldo_va28 {
+				regulator-compatible = "ldo_va28";
+				regulator-name = "va28";
+				regulator-always-on;
+			};
+
+			mt6397_vcama_reg: ldo_vcama {
+				regulator-compatible = "ldo_vcama";
+				regulator-name = "vcama";
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vio28_reg: ldo_vio28 {
+				regulator-compatible = "ldo_vio28";
+				regulator-name = "vio28";
+				regulator-always-on;
+			};
+
+			mt6397_vusb_reg: ldo_vusb {
+				regulator-compatible = "ldo_vusb";
+				regulator-name = "vusb";
+			};
+
+			mt6397_vmc_reg: ldo_vmc {
+				regulator-compatible = "ldo_vmc";
+				regulator-name = "vmc";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vmch_reg: ldo_vmch {
+				regulator-compatible = "ldo_vmch";
+				regulator-name = "vmch";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vemc_3v3_reg: ldo_vemc3v3 {
+				regulator-compatible = "ldo_vemc3v3";
+				regulator-name = "vemc_3v3";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp1_reg: ldo_vgp1 {
+				regulator-compatible = "ldo_vgp1";
+				regulator-name = "vcamd";
+				regulator-min-microvolt = <1220000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <240>;
+			};
+
+			mt6397_vgp2_reg: ldo_vgp2 {
+				regulator-compatible = "ldo_vgp2";
+				regulator-name = "vcamio";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp3_reg: ldo_vgp3 {
+				regulator-compatible = "ldo_vgp3";
+				regulator-name = "vcamaf";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp4_reg: ldo_vgp4 {
+				regulator-compatible = "ldo_vgp4";
+				regulator-name = "vgp4";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp5_reg: ldo_vgp5 {
+				regulator-compatible = "ldo_vgp5";
+				regulator-name = "vgp5";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp6_reg: ldo_vgp6 {
+				regulator-compatible = "ldo_vgp6";
+				regulator-name = "vgp6";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vibr_reg: ldo_vibr {
+				regulator-compatible = "ldo_vibr";
+				regulator-name = "vibr";
+				regulator-min-microvolt = <1300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+		};
+	};
+};
+
 &uart3 {
 	status = "okay";
 };
-- 
2.1.4



From s.hauer at pengutronix.de  Thu Apr 23 02:25:03 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 11:25:03 +0200
Subject: [PATCH v11]: clk: Add common clock support for Mediatek MT8135
 and MT8173
In-Reply-To: <CABuKBeLaUfseZU84vNmVFR3EeUhNrbrXnKeN=N6PP=abPcnjDQ@mail.gmail.com>
References: <1427825817-26773-1-git-send-email-s.hauer@pengutronix.de>
 <CABuKBeJ256HBLP+3WB+acNbMonGknQJgWBnGjEx1VWecWc-Y5g@mail.gmail.com>
 <20150414100810.GH4946@pengutronix.de>
 <CABuKBeLxcCcfcunwX7q=hSHRrrHd5-EMgRzSwhx9eSdvNKum=A@mail.gmail.com>
 <20150414115702.GX9742@pengutronix.de>
 <CABuKBe+MnmL47FB2FhN=RRKEZV4tR3OyVTTpWfkTYQ4zSZP22Q@mail.gmail.com>
 <CABuKBeLaUfseZU84vNmVFR3EeUhNrbrXnKeN=N6PP=abPcnjDQ@mail.gmail.com>
Message-ID: <20150423092503.GL6325@pengutronix.de>

On Wed, Apr 15, 2015 at 05:48:08PM +0200, Matthias Brugger wrote:
> 2015-04-15 17:11 GMT+02:00 Matthias Brugger <matthias.bgg at gmail.com>:
> > 2015-04-14 13:57 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >> On Tue, Apr 14, 2015 at 01:01:30PM +0200, Matthias Brugger wrote:
> >>> Hi Sascha,
> >>>
> >>> 2015-04-14 12:08 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >>> > Hi Matthias,
> >>> >
> >>> > On Tue, Apr 07, 2015 at 01:47:58PM +0200, Matthias Brugger wrote:
> >>> >> Hi Sascha,
> >>> >>
> >>> >>
> >>> >> 2015-03-31 20:16 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >>> >> >
> >>> >> > The following changes since commit 9eccca0843205f87c00404b663188b88eb248051:
> >>> >> >
> >>> >> >   Linux 4.0-rc3 (2015-03-08 16:09:09 -0700)
> >>> >> >
> >>> >> > are available in the git repository at:
> >>> >> >
> >>> >> >   git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v11
> >>> >> >
> >>> >> > for you to fetch changes up to ae9129219143cfdefe8b3a463deb8c5cb8955525:
> >>> >> >
> >>> >> >   dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-31 20:08:46 +0200)
> >>> >> >
> >>> >> > ----------------------------------------------------------------
> >>> >> > This patchset contains the initial common clock support for Mediatek SoCs.
> >>> >> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
> >>> >> > and clock gates.
> >>> >>
> >>> >> I tried the patch set on my mt8135 eval board. I used the dts bindings
> >>> >> from a former version of this set [1], but it does not boot the board
> >>> >> (based on v4.0-rc7).
> >>> >> Do you have any hint, what is happening, or are the bindings wrong?
> >>> >
> >>> > I just tried on a v4.0 with
> >>> > - this series applied
> >>> > - the dts patch applied (which is still up-to-date)
> >>> > - multi_v7_defconfig
> >>> >
> >>> > And it still works. What do you mean with "does not boot the board"? No
> >>> > console output? Could you try with earlyprintk?
> >>>
> >>> The probelms I see is, that with the clock patches, I'm not able to
> >>> boot into a initramfs [1].
> >>> Whereas if I just comment topckgen and preicfg in the dts, I'm able to
> >>> get the a serial console of my initramfs [2].
> >>>
> >>> I wonder if you are able to get serial console from the initramfs with
> >>> the clock patches + dts patch?
> >>
> >> So you get kernel messages but no output from initramfs? In this case
> >> the kernel disables the unused clocks in a late_initcall. The UART
> >> driver still uses the dummy clock provided in the dtsi, so the real
> >> UART clk gets disabled in the initcall. Try passing clk_ignore_unused to
> >> the kernel
> >
> > OK, I can boot to the initramfs with this kernel parameter, but it
> > fails to boot, when I change the uart clock. I suppose that PERI_UART3
> > for debug port uart3 should be fine, but it looks like it doesn't
> > work.
> > I can see on the mt6589 datasheet that you have a register
> > PERI_UART_CK_SOURCE_SEL where you can decide if you want a 26 MHz or a
> > 52 MHz clock for the UART block.
> > Does this register exists on mt8135? If so, why is it not implemented?
> 
> I found that PERI_UARTx_CK is connected to axi_sel but should be
> connected to uart_sel. Like this I'm able to reach to initramfs
> console, but the baud rate values are screwed up.
> As uart_sel is at 52 MHz, I suppose we need to change the entries in
> PERI_UART_CK_SOURCE_SEL.

I sorted the UART clock stuff out. I sent out three series, with all of
them merged together you should get UART + common clock support working
properly on MT835.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr 23 05:01:52 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 23 Apr 2015 14:01:52 +0200
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <20150423120152.GM6325@pengutronix.de>

On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
> This patch implements MT8173 specific cpufreq driver with OPP table defined
> in the driver code.
> 
> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
> ---
>  drivers/cpufreq/Kconfig.arm      |   6 +
>  drivers/cpufreq/Makefile         |   1 +
>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 516 insertions(+)
>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 1b06fc4..25643c7 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -132,6 +132,12 @@ config ARM_KIRKWOOD_CPUFREQ
>  	  This adds the CPUFreq driver for Marvell Kirkwood
>  	  SoCs.
>  
> +config ARM_MT8173_CPUFREQ
> +	bool "Mediatek MT8173 CPUFreq support"
> +	depends on ARCH_MEDIATEK && REGULATOR
> +	help
> +	  This adds the CPUFreq driver support for Mediatek MT8173 SoC.
> +
>  config ARM_OMAP2PLUS_CPUFREQ
>  	bool "TI OMAP2+"
>  	depends on ARCH_OMAP2PLUS
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 82a1821..da9d616 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)	+= highbank-cpufreq.o
>  obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
>  obj-$(CONFIG_ARM_INTEGRATOR)		+= integrator-cpufreq.o
>  obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= kirkwood-cpufreq.o
> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)	+= mt8173-cpufreq.o
>  obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
>  obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
>  obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
> diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
> new file mode 100644
> index 0000000..a310e72
> --- /dev/null
> +++ b/drivers/cpufreq/mt8173-cpufreq.c
> @@ -0,0 +1,509 @@
> +/*
> +* Copyright (c) 2015 Linaro Ltd.
> +* Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
> +*
> +* 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.
> +*/
> +
> +#include <linux/clk.h>
> +#include <linux/cpu.h>
> +#include <linux/cpufreq.h>
> +#include <linux/cpumask.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +
> +#define MIN_VOLT_SHIFT		100000
> +#define MAX_VOLT_SHIFT		200000
> +
> +#define OPP(f, vp, vs) {		\
> +		.freq	= f,		\
> +		.vproc	= vp,		\
> +		.vsram	= vs,		\
> +	}
> +
> +struct mtk_cpu_opp {
> +	unsigned int freq;
> +	int vproc;
> +	int vsram;
> +};
> +
> +/*
> + * The struct cpu_dvfs_info holds necessary information for doing CPU DVFS of
> + * each cluster. For Mediatek SoCs, each CPU cluster in SoC has two voltage
> + * inputs, Vproc and Vsram. For some cluster in SoC, the two voltage inputs are
> + * supplied by different PMICs. In this case, when scaling up/down the voltage
> + * of Vsram and Vproc, the two voltage inputs need to be controlled under a
> + * hardware limitation: 100mV < Vsram - Vproc < 200mV
> + * When scaling up/down the clock frequency of a cluster, the clock source need
> + * to be switched to another stable PLL clock temporarily, and switched back to
> + * the original PLL after the it becomes stable at target frequency.
> + * Hence the voltage inputs of cluster need to be set to an intermediate voltage
> + * before the clock frequency being scaled up/down.
> + */
> +
> +struct cpu_dvfs_info {
> +	cpumask_t cpus;
> +
> +	struct mtk_cpu_opp *opp_tbl;
> +	struct mtk_cpu_opp *intermediate_opp;
> +	int nr_opp;
> +
> +	struct regulator *proc_reg;
> +	struct regulator *sram_reg;
> +	struct clk *cpu_clk;
> +	struct clk *inter_pll;
> +};
> +
> +/*
> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
> + * tree.
> + */
> +
> +/* OPP table for LITTLE cores of MT8173 */
> +struct mtk_cpu_opp mt8173_l_opp[] = {
> +	OPP(507000000, 859000, 0),
> +	OPP(702000000, 908000, 0),
> +	OPP(1001000000, 983000, 0),
> +	OPP(1105000000, 1009000, 0),
> +	OPP(1183000000, 1028000, 0),
> +	OPP(1404000000, 1083000, 0),
> +	OPP(1508000000, 1109000, 0),
> +	OPP(1573000000, 1125000, 0),
> +};
> +
> +/* OPP table for big cores of MT8173 */
> +struct mtk_cpu_opp mt8173_b_opp[] = {
> +	OPP(507000000, 828000, 928000),
> +	OPP(702000000, 867000, 967000),
> +	OPP(1001000000, 927000, 1027000),
> +	OPP(1209000000, 968000, 1068000),
> +	OPP(1404000000, 1007000, 1107000),
> +	OPP(1612000000, 1049000, 1149000),
> +	OPP(1807000000, 1089000, 1150000),
> +	OPP(1989000000, 1125000, 1150000),
> +};

Do you really need the SRAM voltages? Isn't the SRAM voltage just CPU
core voltage + 100mV +- tolerance?

> +
> +static inline int need_voltage_trace(struct cpu_dvfs_info *info)
> +{
> +	return (!IS_ERR_OR_NULL(info->proc_reg) &&
> +		!IS_ERR_OR_NULL(info->sram_reg));
> +}
> +
> +static struct mtk_cpu_opp *cpu_opp_find_freq_ceil(struct mtk_cpu_opp *opp_tbl,
> +						  int nr_opp,
> +						  unsigned long rate)
> +{
> +	int i;
> +
> +	for (i = 0; i < nr_opp; i++)
> +		if (opp_tbl[i].freq >= rate)
> +			return &opp_tbl[i];
> +
> +	return NULL;
> +}
> +
> +/*
> + * Query the exact voltage value that is largest previous to the input voltage
> + * value supported by the regulator
> + */
> +static int get_regulator_voltage_ceil(struct regulator *regulator, int voltage)
> +{
> +	int cnt, i, volt = -1;
> +
> +	if (IS_ERR_OR_NULL(regulator))
> +		return -EINVAL;
> +
> +	cnt = regulator_count_voltages(regulator);
> +	for (i = 0; i < cnt && volt < voltage; i++)
> +		volt = regulator_list_voltage(regulator, i);
> +
> +	return (i >= cnt) ? -EINVAL : volt;
> +}
> +
> +/*
> + * Query the exact voltage value that is smallest following to the input voltage
> + * value supported by the regulator
> + */
> +static int get_regulator_voltage_floor(struct regulator *regulator, int voltage)
> +{
> +	int cnt, i, volt = -1;
> +
> +	if (IS_ERR_OR_NULL(regulator))
> +		return -EINVAL;
> +
> +	cnt = regulator_count_voltages(regulator);
> +	/* skip all trailing 0s in the list of supported voltages */
> +	for (i = cnt - 1; i >= 0 && volt <= 0; i--)
> +		volt = regulator_list_voltage(regulator, i);
> +
> +	for (; i >= 0; i--) {
> +		volt = regulator_list_voltage(regulator, i);
> +		if (volt <= voltage)
> +			return volt;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
> +				     struct mtk_cpu_opp *opp)
> +{
> +	struct regulator *proc_reg = info->proc_reg;
> +	struct regulator *sram_reg = info->sram_reg;
> +	int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
> +
> +	old_vproc = regulator_get_voltage(proc_reg);
> +	old_vsram = regulator_get_voltage(sram_reg);
> +
> +	new_vproc = opp->vproc;
> +	new_vsram = opp->vsram;
> +
> +	/*
> +	 * In the case the voltage is going to be scaled up, Vsram and Vproc
> +	 * need to be scaled up step by step. In each step, Vsram needs to be
> +	 * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
> +	 * Repeat the step until Vsram and Vproc are set to target voltage.
> +	 */
> +	if (old_vproc < new_vproc) {
> +next_up_step:
> +		old_vsram = regulator_get_voltage(sram_reg);
> +
> +		vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
> +			new_vsram : old_vproc + MAX_VOLT_SHIFT;
> +		vsram = get_regulator_voltage_floor(sram_reg, vsram);
> +
> +		ret = regulator_set_voltage(sram_reg, vsram, vsram);
> +		if (ret)
> +			return ret;

This introspecting the regulators for possible voltages looks hacky and
unnecessary. regulator_set_voltage() can be passed minimum and maximum
values, why don't you use it to increase the voltage within sensible
limit, like

	regulator_set_voltage(sram_reg, old_vsram + 100000, old_vsram + 200000);

or similar?

> +
> +		vproc = (new_vsram == vsram) ?
> +			new_vproc : vsram - MIN_VOLT_SHIFT;
> +		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
> +
> +		ret = regulator_set_voltage(proc_reg, vproc, vproc);
> +		if (ret) {
> +			regulator_set_voltage(sram_reg, old_vsram, old_vsram);
> +			return ret;
> +		}
> +
> +		if (new_vproc == vproc && new_vsram == vsram)
> +			return 0;

Here you assume that the voltages can be exactly reached. That does not
need to be the case, for example with a different PMIC.

> +
> +		old_vproc = vproc;
> +		goto next_up_step;

Use C loop instructions to create loops. Using gotos for loops creates
readable code only in very rare cases (and this is not one of those)

> +
> +	/*
> +	 * In the case the voltage is going to be scaled down, Vsram and Vproc
> +	 * need to be scaled down step by step. In each step, Vproc needs to be
> +	 * set to (Vsram - 200mV) first, then Vproc is set to (Vproc + 100mV).
> +	 * Repeat the step until Vsram and Vproc are set to target voltage.
> +	 */
> +	} else if (old_vproc > new_vproc) {
> +next_down_step:
> +		old_vproc = regulator_get_voltage(proc_reg);
> +
> +		vproc = (old_vsram - new_vproc < MAX_VOLT_SHIFT) ?
> +			new_vproc : old_vsram - MAX_VOLT_SHIFT;
> +		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
> +
> +		ret = regulator_set_voltage(proc_reg, vproc, vproc);
> +		if (ret)
> +			return ret;
> +
> +		vsram = (new_vproc == vproc) ?
> +			new_vsram : vproc + MIN_VOLT_SHIFT;
> +		vsram = get_regulator_voltage_floor(sram_reg, vsram);
> +
> +		ret = regulator_set_voltage(sram_reg, vsram, vsram);
> +		if (ret) {
> +			regulator_set_voltage(proc_reg, old_vproc, old_vproc);
> +			return ret;
> +		}
> +
> +		if (new_vproc == vproc && new_vsram == vsram)
> +			return 0;
> +
> +		old_vsram = vsram;
> +		goto next_down_step;
> +	}
> +
> +	WARN_ON(1);

Why warn? You have nothing to do and that should be just fine.

> +	return 0;
> +}
> +
> +static int mt8173_cpufreq_set_voltage(struct cpu_dvfs_info *info,
> +				      struct mtk_cpu_opp *opp)
> +{
> +	if (need_voltage_trace(info))
> +		return mtk_cpufreq_voltage_trace(info, opp);
> +	else
> +		return regulator_set_voltage(info->proc_reg, opp->vproc,
> +					     opp->vproc);
> +}
> +
> +static int mt8173_cpufreq_set_target(struct cpufreq_policy *policy,
> +				     unsigned int index)
> +{
> +	struct cpufreq_frequency_table *freq_table = policy->freq_table;
> +	struct clk *cpu_clk = policy->clk;
> +	struct clk *armpll = clk_get_parent(cpu_clk);
> +	struct cpu_dvfs_info *info;
> +	struct mtk_cpu_opp *new_opp, *target_opp, *inter_opp, *orig_opp;
> +	long freq_hz, orig_freq_hz;
> +	int old_vproc, ret;
> +
> +	info = (struct cpu_dvfs_info *)policy->driver_data;
> +	inter_opp = info->intermediate_opp;
> +	orig_freq_hz = clk_get_rate(cpu_clk);
> +	orig_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp,
> +					  orig_freq_hz);
> +	if (!orig_opp)
> +		return -EINVAL;
> +
> +	old_vproc = regulator_get_voltage(info->proc_reg);
> +	freq_hz = freq_table[index].frequency * 1000;
> +	new_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp, freq_hz);

Since the frequency table and the opp_tbl have the same indices:

	new_opp = info->opp_tbl[index];

> +	target_opp = new_opp;
> +
> +	if (!new_opp)
> +		return -EINVAL;
> +
> +	if (target_opp->vproc < inter_opp->vproc)
> +		target_opp = info->intermediate_opp;
> +
> +	if (old_vproc < target_opp->vproc) {

old_vproc is used only once, so using regulator_get_voltage(info->proc_reg)
directly here make the code clearer.

> +		ret = mt8173_cpufreq_set_voltage(info, target_opp);
> +		if (ret) {
> +			pr_err("cpu%d: failed to scale up voltage!\n",
> +			       policy->cpu);
> +			mt8173_cpufreq_set_voltage(info, orig_opp);
> +			return ret;
> +		}
> +	}
> +
> +	ret = clk_set_parent(cpu_clk, info->inter_pll);
> +	if (ret) {
> +		pr_err("cpu%d: failed to re-parent cpu clock!\n",
> +		       policy->cpu);
> +		mt8173_cpufreq_set_voltage(info, orig_opp);
> +		WARN_ON(1);
> +		return ret;
> +	}
> +
> +	ret = clk_set_rate(armpll, freq_hz);
> +	if (ret) {
> +		pr_err("cpu%d: failed to scale cpu clock rate!\n",
> +		       policy->cpu);
> +		clk_set_parent(cpu_clk, armpll);
> +		mt8173_cpufreq_set_voltage(info, orig_opp);
> +		return ret;
> +	}
> +
> +	ret = clk_set_parent(cpu_clk, armpll);
> +	if (ret) {
> +		pr_err("cpu%d: failed to re-parent cpu clock!\n",
> +		       policy->cpu);
> +		mt8173_cpufreq_set_voltage(info, inter_opp);
> +		WARN_ON(1);
> +		return ret;
> +	}
> +
> +	if (new_opp->vproc < inter_opp->vproc) {
> +		ret = mt8173_cpufreq_set_voltage(info, new_opp);
> +		if (ret) {
> +			pr_err("cpu%d: failed to scale down voltage!\n",
> +			       policy->cpu);
> +			clk_set_parent(cpu_clk, info->inter_pll);
> +			clk_set_rate(armpll, orig_freq_hz);
> +			clk_set_parent(cpu_clk, armpll);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt8173_cpufreq_cpu_opp_fixup(struct cpu_dvfs_info *info)
> +{
> +	struct mtk_cpu_opp *opp_tbl = info->opp_tbl;
> +	struct regulator *proc_reg = info->proc_reg;
> +	struct regulator *sram_reg = info->sram_reg;
> +	int vproc, vsram, i;
> +
> +	for (i = 0; i < info->nr_opp; i++) {
> +		vproc = opp_tbl[i].vproc;
> +		vsram = opp_tbl[i].vsram;
> +
> +		vproc = get_regulator_voltage_ceil(proc_reg, vproc);
> +
> +		if (!IS_ERR_OR_NULL(sram_reg))
> +			vsram = get_regulator_voltage_ceil(sram_reg, vsram);
> +
> +		if (vproc < 0 || (!IS_ERR_OR_NULL(sram_reg) && vsram < 0)) {
> +			pr_err("%s: Failed to get voltage setting of OPPs\n",
> +			       __func__);
> +			return -EINVAL;
> +		}
> +
> +		opp_tbl[i].vproc = vproc;
> +		opp_tbl[i].vsram = vsram;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt8173_cpufreq_dvfs_init(struct cpu_dvfs_info *info)
> +{
> +	struct device *cpu_dev;
> +	struct regulator *proc_reg, *sram_reg;
> +	struct clk *cpu_clk, *inter_pll;
> +	unsigned long rate;
> +	int cpu, ret;
> +
> +	cpu = cpumask_first(&info->cpus);
> +
> +try_next_cpu:
> +	cpu_dev = get_cpu_device(cpu);
> +	proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> +	sram_reg = regulator_get_exclusive(cpu_dev, "sram");
> +	cpu_clk = clk_get(cpu_dev, "cpu");
> +	inter_pll = clk_get(cpu_dev, "intermediate");
> +
> +	if (IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(cpu_clk) ||
> +	    IS_ERR_OR_NULL(inter_pll)) {
> +		cpu = cpumask_next(cpu, &info->cpus);
> +		if (cpu >= nr_cpu_ids)
> +			return -ENODEV;
> +
> +		goto try_next_cpu;
> +	}

Use a loop.

> +
> +	/* Both PROC and SRAM regulators are present. This is a big
> +	 * cluster, and needs to do voltage tracing. */
> +	if (!(IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(sram_reg))) {
> +		info->opp_tbl = mt8173_b_opp;
> +		info->nr_opp = sizeof(mt8173_b_opp) / sizeof(mt8173_b_opp[0]);
> +	} else {
> +		info->opp_tbl = mt8173_l_opp;
> +		info->nr_opp = sizeof(mt8173_l_opp) / sizeof(mt8173_l_opp[0]);
> +	}
> +
> +	info->proc_reg = proc_reg;
> +	info->sram_reg = sram_reg;
> +	info->cpu_clk = cpu_clk;
> +	info->inter_pll = inter_pll;
> +
> +	ret = mt8173_cpufreq_cpu_opp_fixup(info);
> +	if (ret) {
> +		pr_err("%s: Failed to fixup opp table: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	rate = clk_get_rate(info->inter_pll);
> +	info->intermediate_opp = cpu_opp_find_freq_ceil(info->opp_tbl,
> +							info->nr_opp,
> +							rate);
> +	if (!info->intermediate_opp) {
> +		pr_err("%s: Failed to setup intermediate opp\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mt8173_cpufreq_dvfs_release(struct cpu_dvfs_info *info)
> +{
> +	regulator_put(info->proc_reg);
> +	regulator_put(info->sram_reg);
> +	clk_put(info->cpu_clk);
> +	clk_put(info->inter_pll);
> +
> +	kfree(info);
> +}
> +
> +static int mt8173_cpufreq_init(struct cpufreq_policy *policy)
> +{
> +	struct cpu_dvfs_info *info;
> +	struct cpufreq_frequency_table *freq_table;
> +	int ret, i;
> +
> +	info = kzalloc(sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	cpumask_copy(&info->cpus, &cpu_topology[policy->cpu].core_sibling);
> +	ret = mt8173_cpufreq_dvfs_init(info);
> +	if (ret) {
> +		pr_err("%s: Failed to initialize DVFS info: %d\n", __func__,
> +		       ret);
> +		goto out_dvfs_release;
> +	}
> +
> +	freq_table = kcalloc(info->nr_opp, sizeof(*freq_table), GFP_KERNEL);
> +	if (!freq_table) {
> +		ret = -ENOMEM;
> +		goto out_dvfs_release;
> +	}
> +
> +	for (i = 0; i < info->nr_opp; i++)
> +		freq_table[i].frequency = info->opp_tbl[i].freq / 1000;
> +
> +	freq_table[i].frequency = CPUFREQ_TABLE_END;

You are corrupting memory here.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From mark.rutland at arm.com  Thu Apr 23 05:53:58 2015
From: mark.rutland at arm.com (Mark Rutland)
Date: Thu, 23 Apr 2015 13:53:58 +0100
Subject: [PATCH 2/2] ARM64: mt8173: dts Add MT8173 cpufreq driver support
In-Reply-To: <1429522047-16675-3-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-3-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <20150423125358.GA29702@leverpostej>

On Mon, Apr 20, 2015 at 10:27:27AM +0100, pi-cheng.chen wrote:
> This patch adds voltage supplies and clocks used by MT8173 cpufreq driver.
> 
> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>

This series has no bindings for these properties.

> ---
>  arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 9 +++++++++
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi    | 6 ++++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
> index 96e141c..7a00cfe 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
> +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
> @@ -330,3 +330,12 @@
>  	status = "okay";
>  	clock-frequency = <100000>;
>  };
> +
> +&cpu0 {
> +	proc-supply = <&mt6397_vpca15_reg>;
> +};
> +
> +&cpu2 {
> +	proc-supply = <&da9211_vcpu_reg>;
> +	sram-supply = <&mt6397_vsramca7_reg>;
> +};


Why do only two CPUs have these properties, and why does one need an
sram-supply?

> diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> index d9cc84e..b8a5454 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> @@ -51,6 +51,9 @@
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a53";
>  			reg = <0x000>;
> +			clocks = <&infracfg INFRA_CA53SEL>,
> +				 <&apmixedsys APMIXED_MAINPLL>;
> +			clock-names = "cpu", "intermediate";
>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -65,6 +68,9 @@
>  			compatible = "arm,cortex-a57";
>  			reg = <0x100>;
>  			enable-method = "psci";
> +			clocks = <&infracfg INFRA_CA57SEL>,
> +				 <&apmixedsys APMIXED_MAINPLL>;
> +			clock-names = "cpu", "intermediate";
>  		};

We should really describe this information per-cpu rather than assuming
that it's the same for siblings. Arbitrarily making one CPU in each
cluster (or other arbitrary grouping) special for the binding is silly.

Mark.


From mark.rutland at arm.com  Thu Apr 23 05:56:23 2015
From: mark.rutland at arm.com (Mark Rutland)
Date: Thu, 23 Apr 2015 13:56:23 +0100
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <20150423125620.GB29702@leverpostej>

> +/*
> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
> + * tree.
> + */
> +
> +/* OPP table for LITTLE cores of MT8173 */
> +struct mtk_cpu_opp mt8173_l_opp[] = {
> +       OPP(507000000, 859000, 0),
> +       OPP(702000000, 908000, 0),
> +       OPP(1001000000, 983000, 0),
> +       OPP(1105000000, 1009000, 0),
> +       OPP(1183000000, 1028000, 0),
> +       OPP(1404000000, 1083000, 0),
> +       OPP(1508000000, 1109000, 0),
> +       OPP(1573000000, 1125000, 0),
> +};
> +
> +/* OPP table for big cores of MT8173 */
> +struct mtk_cpu_opp mt8173_b_opp[] = {
> +       OPP(507000000, 828000, 928000),
> +       OPP(702000000, 867000, 967000),
> +       OPP(1001000000, 927000, 1027000),
> +       OPP(1209000000, 968000, 1068000),
> +       OPP(1404000000, 1007000, 1107000),
> +       OPP(1612000000, 1049000, 1149000),
> +       OPP(1807000000, 1089000, 1150000),
> +       OPP(1989000000, 1125000, 1150000),
> +};

We should sort out the OPP bindings if we need to sort out the OPP
bindings. We can't remove these once they're in without causing pain for
everyone with an old DTB.

Mark.


From pi-cheng.chen at linaro.org  Thu Apr 23 23:46:25 2015
From: pi-cheng.chen at linaro.org (Pi-Cheng Chen)
Date: Fri, 24 Apr 2015 14:46:25 +0800
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <20150423120152.GM6325@pengutronix.de>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150423120152.GM6325@pengutronix.de>
Message-ID: <CALx668VsT60+kx7o-ZM5Wxk7Nn-rXS21O5SDYr++EeY-zEJ6ew@mail.gmail.com>

Hi Sascha,

Thanks for reviewing.

On Thu, Apr 23, 2015 at 8:01 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
>> This patch implements MT8173 specific cpufreq driver with OPP table defined
>> in the driver code.
>>
>> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
>> ---
>>  drivers/cpufreq/Kconfig.arm      |   6 +
>>  drivers/cpufreq/Makefile         |   1 +
>>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 516 insertions(+)
>>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 1b06fc4..25643c7 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -132,6 +132,12 @@ config ARM_KIRKWOOD_CPUFREQ
>>         This adds the CPUFreq driver for Marvell Kirkwood
>>         SoCs.
>>
>> +config ARM_MT8173_CPUFREQ
>> +     bool "Mediatek MT8173 CPUFreq support"
>> +     depends on ARCH_MEDIATEK && REGULATOR
>> +     help
>> +       This adds the CPUFreq driver support for Mediatek MT8173 SoC.
>> +
>>  config ARM_OMAP2PLUS_CPUFREQ
>>       bool "TI OMAP2+"
>>       depends on ARCH_OMAP2PLUS
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 82a1821..da9d616 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)  += highbank-cpufreq.o
>>  obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)              += imx6q-cpufreq.o
>>  obj-$(CONFIG_ARM_INTEGRATOR)         += integrator-cpufreq.o
>>  obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)   += kirkwood-cpufreq.o
>> +obj-$(CONFIG_ARM_MT8173_CPUFREQ)     += mt8173-cpufreq.o
>>  obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)  += omap-cpufreq.o
>>  obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)     += pxa2xx-cpufreq.o
>>  obj-$(CONFIG_PXA3xx)                 += pxa3xx-cpufreq.o
>> diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
>> new file mode 100644
>> index 0000000..a310e72
>> --- /dev/null
>> +++ b/drivers/cpufreq/mt8173-cpufreq.c
>> @@ -0,0 +1,509 @@
>> +/*
>> +* Copyright (c) 2015 Linaro Ltd.
>> +* Author: Pi-Cheng Chen <pi-cheng.chen at linaro.org>
>> +*
>> +* 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.
>> +*/
>> +
>> +#include <linux/clk.h>
>> +#include <linux/cpu.h>
>> +#include <linux/cpufreq.h>
>> +#include <linux/cpumask.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/slab.h>
>> +
>> +#define MIN_VOLT_SHIFT               100000
>> +#define MAX_VOLT_SHIFT               200000
>> +
>> +#define OPP(f, vp, vs) {             \
>> +             .freq   = f,            \
>> +             .vproc  = vp,           \
>> +             .vsram  = vs,           \
>> +     }
>> +
>> +struct mtk_cpu_opp {
>> +     unsigned int freq;
>> +     int vproc;
>> +     int vsram;
>> +};
>> +
>> +/*
>> + * The struct cpu_dvfs_info holds necessary information for doing CPU DVFS of
>> + * each cluster. For Mediatek SoCs, each CPU cluster in SoC has two voltage
>> + * inputs, Vproc and Vsram. For some cluster in SoC, the two voltage inputs are
>> + * supplied by different PMICs. In this case, when scaling up/down the voltage
>> + * of Vsram and Vproc, the two voltage inputs need to be controlled under a
>> + * hardware limitation: 100mV < Vsram - Vproc < 200mV
>> + * When scaling up/down the clock frequency of a cluster, the clock source need
>> + * to be switched to another stable PLL clock temporarily, and switched back to
>> + * the original PLL after the it becomes stable at target frequency.
>> + * Hence the voltage inputs of cluster need to be set to an intermediate voltage
>> + * before the clock frequency being scaled up/down.
>> + */
>> +
>> +struct cpu_dvfs_info {
>> +     cpumask_t cpus;
>> +
>> +     struct mtk_cpu_opp *opp_tbl;
>> +     struct mtk_cpu_opp *intermediate_opp;
>> +     int nr_opp;
>> +
>> +     struct regulator *proc_reg;
>> +     struct regulator *sram_reg;
>> +     struct clk *cpu_clk;
>> +     struct clk *inter_pll;
>> +};
>> +
>> +/*
>> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
>> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
>> + * tree.
>> + */
>> +
>> +/* OPP table for LITTLE cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_l_opp[] = {
>> +     OPP(507000000, 859000, 0),
>> +     OPP(702000000, 908000, 0),
>> +     OPP(1001000000, 983000, 0),
>> +     OPP(1105000000, 1009000, 0),
>> +     OPP(1183000000, 1028000, 0),
>> +     OPP(1404000000, 1083000, 0),
>> +     OPP(1508000000, 1109000, 0),
>> +     OPP(1573000000, 1125000, 0),
>> +};
>> +
>> +/* OPP table for big cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_b_opp[] = {
>> +     OPP(507000000, 828000, 928000),
>> +     OPP(702000000, 867000, 967000),
>> +     OPP(1001000000, 927000, 1027000),
>> +     OPP(1209000000, 968000, 1068000),
>> +     OPP(1404000000, 1007000, 1107000),
>> +     OPP(1612000000, 1049000, 1149000),
>> +     OPP(1807000000, 1089000, 1150000),
>> +     OPP(1989000000, 1125000, 1150000),
>> +};
>
> Do you really need the SRAM voltages? Isn't the SRAM voltage just CPU
> core voltage + 100mV +- tolerance?

Yes, that was also my original idea to describe the OPPs with only (volt, vproc)
pair in device tree and calculate the SRAM voltages in driver code. One of the
reason to put SRAM voltages in the table is that I think it will make the code
cleaner since we are actually controlling 2 regulators at each OPP. But you're
right, we don't really need it. I'm fine with both approaches. Just
not sure which
way is more proper.

The other reason to put this table with SRAM voltages is that I want to fixup
all voltage values by querying the supported voltages of regulators so that
it will be easier to do "voltage trace".

>
>> +
>> +static inline int need_voltage_trace(struct cpu_dvfs_info *info)
>> +{
>> +     return (!IS_ERR_OR_NULL(info->proc_reg) &&
>> +             !IS_ERR_OR_NULL(info->sram_reg));
>> +}
>> +
>> +static struct mtk_cpu_opp *cpu_opp_find_freq_ceil(struct mtk_cpu_opp *opp_tbl,
>> +                                               int nr_opp,
>> +                                               unsigned long rate)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i < nr_opp; i++)
>> +             if (opp_tbl[i].freq >= rate)
>> +                     return &opp_tbl[i];
>> +
>> +     return NULL;
>> +}
>> +
>> +/*
>> + * Query the exact voltage value that is largest previous to the input voltage
>> + * value supported by the regulator
>> + */
>> +static int get_regulator_voltage_ceil(struct regulator *regulator, int voltage)
>> +{
>> +     int cnt, i, volt = -1;
>> +
>> +     if (IS_ERR_OR_NULL(regulator))
>> +             return -EINVAL;
>> +
>> +     cnt = regulator_count_voltages(regulator);
>> +     for (i = 0; i < cnt && volt < voltage; i++)
>> +             volt = regulator_list_voltage(regulator, i);
>> +
>> +     return (i >= cnt) ? -EINVAL : volt;
>> +}
>> +
>> +/*
>> + * Query the exact voltage value that is smallest following to the input voltage
>> + * value supported by the regulator
>> + */
>> +static int get_regulator_voltage_floor(struct regulator *regulator, int voltage)
>> +{
>> +     int cnt, i, volt = -1;
>> +
>> +     if (IS_ERR_OR_NULL(regulator))
>> +             return -EINVAL;
>> +
>> +     cnt = regulator_count_voltages(regulator);
>> +     /* skip all trailing 0s in the list of supported voltages */
>> +     for (i = cnt - 1; i >= 0 && volt <= 0; i--)
>> +             volt = regulator_list_voltage(regulator, i);
>> +
>> +     for (; i >= 0; i--) {
>> +             volt = regulator_list_voltage(regulator, i);
>> +             if (volt <= voltage)
>> +                     return volt;
>> +     }
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
>> +                                  struct mtk_cpu_opp *opp)
>> +{
>> +     struct regulator *proc_reg = info->proc_reg;
>> +     struct regulator *sram_reg = info->sram_reg;
>> +     int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
>> +
>> +     old_vproc = regulator_get_voltage(proc_reg);
>> +     old_vsram = regulator_get_voltage(sram_reg);
>> +
>> +     new_vproc = opp->vproc;
>> +     new_vsram = opp->vsram;
>> +
>> +     /*
>> +      * In the case the voltage is going to be scaled up, Vsram and Vproc
>> +      * need to be scaled up step by step. In each step, Vsram needs to be
>> +      * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
>> +      * Repeat the step until Vsram and Vproc are set to target voltage.
>> +      */
>> +     if (old_vproc < new_vproc) {
>> +next_up_step:
>> +             old_vsram = regulator_get_voltage(sram_reg);
>> +
>> +             vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
>> +                     new_vsram : old_vproc + MAX_VOLT_SHIFT;
>> +             vsram = get_regulator_voltage_floor(sram_reg, vsram);
>> +
>> +             ret = regulator_set_voltage(sram_reg, vsram, vsram);
>> +             if (ret)
>> +                     return ret;
>
> This introspecting the regulators for possible voltages looks hacky and
> unnecessary. regulator_set_voltage() can be passed minimum and maximum
> values, why don't you use it to increase the voltage within sensible
> limit, like
>
>         regulator_set_voltage(sram_reg, old_vsram + 100000, old_vsram + 200000);
>
> or similar?

I am sorry I don't understand how could I do it. Would you elaborate?

>
>> +
>> +             vproc = (new_vsram == vsram) ?
>> +                     new_vproc : vsram - MIN_VOLT_SHIFT;
>> +             vproc = get_regulator_voltage_ceil(proc_reg, vproc);
>> +
>> +             ret = regulator_set_voltage(proc_reg, vproc, vproc);
>> +             if (ret) {
>> +                     regulator_set_voltage(sram_reg, old_vsram, old_vsram);
>> +                     return ret;
>> +             }
>> +
>> +             if (new_vproc == vproc && new_vsram == vsram)
>> +                     return 0;
>
> Here you assume that the voltages can be exactly reached. That does not
> need to be the case, for example with a different PMIC.

That's why I try to fixup all voltage values during initialization. Please check
mt8173_cpufreq_cpu_opp_fixup() below.

>
>> +
>> +             old_vproc = vproc;
>> +             goto next_up_step;
>
> Use C loop instructions to create loops. Using gotos for loops creates
> readable code only in very rare cases (and this is not one of those)

Will do it.

>
>> +
>> +     /*
>> +      * In the case the voltage is going to be scaled down, Vsram and Vproc
>> +      * need to be scaled down step by step. In each step, Vproc needs to be
>> +      * set to (Vsram - 200mV) first, then Vproc is set to (Vproc + 100mV).
>> +      * Repeat the step until Vsram and Vproc are set to target voltage.
>> +      */
>> +     } else if (old_vproc > new_vproc) {
>> +next_down_step:
>> +             old_vproc = regulator_get_voltage(proc_reg);
>> +
>> +             vproc = (old_vsram - new_vproc < MAX_VOLT_SHIFT) ?
>> +                     new_vproc : old_vsram - MAX_VOLT_SHIFT;
>> +             vproc = get_regulator_voltage_ceil(proc_reg, vproc);
>> +
>> +             ret = regulator_set_voltage(proc_reg, vproc, vproc);
>> +             if (ret)
>> +                     return ret;
>> +
>> +             vsram = (new_vproc == vproc) ?
>> +                     new_vsram : vproc + MIN_VOLT_SHIFT;
>> +             vsram = get_regulator_voltage_floor(sram_reg, vsram);
>> +
>> +             ret = regulator_set_voltage(sram_reg, vsram, vsram);
>> +             if (ret) {
>> +                     regulator_set_voltage(proc_reg, old_vproc, old_vproc);
>> +                     return ret;
>> +             }
>> +
>> +             if (new_vproc == vproc && new_vsram == vsram)
>> +                     return 0;
>> +
>> +             old_vsram = vsram;
>> +             goto next_down_step;
>> +     }
>> +
>> +     WARN_ON(1);
>
> Why warn? You have nothing to do and that should be just fine.

OK. Will remove it.

>
>> +     return 0;
>> +}
>> +
>> +static int mt8173_cpufreq_set_voltage(struct cpu_dvfs_info *info,
>> +                                   struct mtk_cpu_opp *opp)
>> +{
>> +     if (need_voltage_trace(info))
>> +             return mtk_cpufreq_voltage_trace(info, opp);
>> +     else
>> +             return regulator_set_voltage(info->proc_reg, opp->vproc,
>> +                                          opp->vproc);
>> +}
>> +
>> +static int mt8173_cpufreq_set_target(struct cpufreq_policy *policy,
>> +                                  unsigned int index)
>> +{
>> +     struct cpufreq_frequency_table *freq_table = policy->freq_table;
>> +     struct clk *cpu_clk = policy->clk;
>> +     struct clk *armpll = clk_get_parent(cpu_clk);
>> +     struct cpu_dvfs_info *info;
>> +     struct mtk_cpu_opp *new_opp, *target_opp, *inter_opp, *orig_opp;
>> +     long freq_hz, orig_freq_hz;
>> +     int old_vproc, ret;
>> +
>> +     info = (struct cpu_dvfs_info *)policy->driver_data;
>> +     inter_opp = info->intermediate_opp;
>> +     orig_freq_hz = clk_get_rate(cpu_clk);
>> +     orig_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp,
>> +                                       orig_freq_hz);
>> +     if (!orig_opp)
>> +             return -EINVAL;
>> +
>> +     old_vproc = regulator_get_voltage(info->proc_reg);
>> +     freq_hz = freq_table[index].frequency * 1000;
>> +     new_opp = cpu_opp_find_freq_ceil(info->opp_tbl, info->nr_opp, freq_hz);
>
> Since the frequency table and the opp_tbl have the same indices:
>
>         new_opp = info->opp_tbl[index];

Will do it.

>
>> +     target_opp = new_opp;
>> +
>> +     if (!new_opp)
>> +             return -EINVAL;
>> +
>> +     if (target_opp->vproc < inter_opp->vproc)
>> +             target_opp = info->intermediate_opp;
>> +
>> +     if (old_vproc < target_opp->vproc) {
>
> old_vproc is used only once, so using regulator_get_voltage(info->proc_reg)
> directly here make the code clearer.

Will do it.

>
>> +             ret = mt8173_cpufreq_set_voltage(info, target_opp);
>> +             if (ret) {
>> +                     pr_err("cpu%d: failed to scale up voltage!\n",
>> +                            policy->cpu);
>> +                     mt8173_cpufreq_set_voltage(info, orig_opp);
>> +                     return ret;
>> +             }
>> +     }
>> +
>> +     ret = clk_set_parent(cpu_clk, info->inter_pll);
>> +     if (ret) {
>> +             pr_err("cpu%d: failed to re-parent cpu clock!\n",
>> +                    policy->cpu);
>> +             mt8173_cpufreq_set_voltage(info, orig_opp);
>> +             WARN_ON(1);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_rate(armpll, freq_hz);
>> +     if (ret) {
>> +             pr_err("cpu%d: failed to scale cpu clock rate!\n",
>> +                    policy->cpu);
>> +             clk_set_parent(cpu_clk, armpll);
>> +             mt8173_cpufreq_set_voltage(info, orig_opp);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_parent(cpu_clk, armpll);
>> +     if (ret) {
>> +             pr_err("cpu%d: failed to re-parent cpu clock!\n",
>> +                    policy->cpu);
>> +             mt8173_cpufreq_set_voltage(info, inter_opp);
>> +             WARN_ON(1);
>> +             return ret;
>> +     }
>> +
>> +     if (new_opp->vproc < inter_opp->vproc) {
>> +             ret = mt8173_cpufreq_set_voltage(info, new_opp);
>> +             if (ret) {
>> +                     pr_err("cpu%d: failed to scale down voltage!\n",
>> +                            policy->cpu);
>> +                     clk_set_parent(cpu_clk, info->inter_pll);
>> +                     clk_set_rate(armpll, orig_freq_hz);
>> +                     clk_set_parent(cpu_clk, armpll);
>> +                     return ret;
>> +             }
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int mt8173_cpufreq_cpu_opp_fixup(struct cpu_dvfs_info *info)
>> +{
>> +     struct mtk_cpu_opp *opp_tbl = info->opp_tbl;
>> +     struct regulator *proc_reg = info->proc_reg;
>> +     struct regulator *sram_reg = info->sram_reg;
>> +     int vproc, vsram, i;
>> +
>> +     for (i = 0; i < info->nr_opp; i++) {
>> +             vproc = opp_tbl[i].vproc;
>> +             vsram = opp_tbl[i].vsram;
>> +
>> +             vproc = get_regulator_voltage_ceil(proc_reg, vproc);
>> +
>> +             if (!IS_ERR_OR_NULL(sram_reg))
>> +                     vsram = get_regulator_voltage_ceil(sram_reg, vsram);
>> +
>> +             if (vproc < 0 || (!IS_ERR_OR_NULL(sram_reg) && vsram < 0)) {
>> +                     pr_err("%s: Failed to get voltage setting of OPPs\n",
>> +                            __func__);
>> +                     return -EINVAL;
>> +             }
>> +
>> +             opp_tbl[i].vproc = vproc;
>> +             opp_tbl[i].vsram = vsram;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int mt8173_cpufreq_dvfs_init(struct cpu_dvfs_info *info)
>> +{
>> +     struct device *cpu_dev;
>> +     struct regulator *proc_reg, *sram_reg;
>> +     struct clk *cpu_clk, *inter_pll;
>> +     unsigned long rate;
>> +     int cpu, ret;
>> +
>> +     cpu = cpumask_first(&info->cpus);
>> +
>> +try_next_cpu:
>> +     cpu_dev = get_cpu_device(cpu);
>> +     proc_reg = regulator_get_exclusive(cpu_dev, "proc");
>> +     sram_reg = regulator_get_exclusive(cpu_dev, "sram");
>> +     cpu_clk = clk_get(cpu_dev, "cpu");
>> +     inter_pll = clk_get(cpu_dev, "intermediate");
>> +
>> +     if (IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(cpu_clk) ||
>> +         IS_ERR_OR_NULL(inter_pll)) {
>> +             cpu = cpumask_next(cpu, &info->cpus);
>> +             if (cpu >= nr_cpu_ids)
>> +                     return -ENODEV;
>> +
>> +             goto try_next_cpu;
>> +     }
>
> Use a loop.

Will do it. Or maybe we don't need a loop here if we have these information
per CPU in the device tree as suggested later in this series by Mark.

>
>> +
>> +     /* Both PROC and SRAM regulators are present. This is a big
>> +      * cluster, and needs to do voltage tracing. */
>> +     if (!(IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(sram_reg))) {
>> +             info->opp_tbl = mt8173_b_opp;
>> +             info->nr_opp = sizeof(mt8173_b_opp) / sizeof(mt8173_b_opp[0]);
>> +     } else {
>> +             info->opp_tbl = mt8173_l_opp;
>> +             info->nr_opp = sizeof(mt8173_l_opp) / sizeof(mt8173_l_opp[0]);
>> +     }
>> +
>> +     info->proc_reg = proc_reg;
>> +     info->sram_reg = sram_reg;
>> +     info->cpu_clk = cpu_clk;
>> +     info->inter_pll = inter_pll;
>> +
>> +     ret = mt8173_cpufreq_cpu_opp_fixup(info);
>> +     if (ret) {
>> +             pr_err("%s: Failed to fixup opp table: %d\n", __func__, ret);
>> +             return ret;
>> +     }
>> +
>> +     rate = clk_get_rate(info->inter_pll);
>> +     info->intermediate_opp = cpu_opp_find_freq_ceil(info->opp_tbl,
>> +                                                     info->nr_opp,
>> +                                                     rate);
>> +     if (!info->intermediate_opp) {
>> +             pr_err("%s: Failed to setup intermediate opp\n", __func__);
>> +             return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static void mt8173_cpufreq_dvfs_release(struct cpu_dvfs_info *info)
>> +{
>> +     regulator_put(info->proc_reg);
>> +     regulator_put(info->sram_reg);
>> +     clk_put(info->cpu_clk);
>> +     clk_put(info->inter_pll);
>> +
>> +     kfree(info);
>> +}
>> +
>> +static int mt8173_cpufreq_init(struct cpufreq_policy *policy)
>> +{
>> +     struct cpu_dvfs_info *info;
>> +     struct cpufreq_frequency_table *freq_table;
>> +     int ret, i;
>> +
>> +     info = kzalloc(sizeof(*info), GFP_KERNEL);
>> +     if (!info)
>> +             return -ENOMEM;
>> +
>> +     cpumask_copy(&info->cpus, &cpu_topology[policy->cpu].core_sibling);
>> +     ret = mt8173_cpufreq_dvfs_init(info);
>> +     if (ret) {
>> +             pr_err("%s: Failed to initialize DVFS info: %d\n", __func__,
>> +                    ret);
>> +             goto out_dvfs_release;
>> +     }
>> +
>> +     freq_table = kcalloc(info->nr_opp, sizeof(*freq_table), GFP_KERNEL);
>> +     if (!freq_table) {
>> +             ret = -ENOMEM;
>> +             goto out_dvfs_release;
>> +     }
>> +
>> +     for (i = 0; i < info->nr_opp; i++)
>> +             freq_table[i].frequency = info->opp_tbl[i].freq / 1000;
>> +
>> +     freq_table[i].frequency = CPUFREQ_TABLE_END;
>
> You are corrupting memory here.

Will fix it.

Thanks for reviewing again.

Best Regards,
Pi-Cheng

>
> Sascha
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From pi-cheng.chen at linaro.org  Thu Apr 23 23:50:04 2015
From: pi-cheng.chen at linaro.org (Pi-Cheng Chen)
Date: Fri, 24 Apr 2015 14:50:04 +0800
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <20150423125620.GB29702@leverpostej>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150423125620.GB29702@leverpostej>
Message-ID: <CALx668W_rj8_UBory5fVa4_i3vLCjgApYCwHoSthXNmx79yH1g@mail.gmail.com>

On Thu, Apr 23, 2015 at 8:56 PM, Mark Rutland <mark.rutland at arm.com> wrote:
>> +/*
>> + * This is a temporary solution until we have new OPPv2 bindings. Therefore we
>> + * could describe the OPPs with (freq, volt, volt) tuple properly in device
>> + * tree.
>> + */
>> +
>> +/* OPP table for LITTLE cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_l_opp[] = {
>> +       OPP(507000000, 859000, 0),
>> +       OPP(702000000, 908000, 0),
>> +       OPP(1001000000, 983000, 0),
>> +       OPP(1105000000, 1009000, 0),
>> +       OPP(1183000000, 1028000, 0),
>> +       OPP(1404000000, 1083000, 0),
>> +       OPP(1508000000, 1109000, 0),
>> +       OPP(1573000000, 1125000, 0),
>> +};
>> +
>> +/* OPP table for big cores of MT8173 */
>> +struct mtk_cpu_opp mt8173_b_opp[] = {
>> +       OPP(507000000, 828000, 928000),
>> +       OPP(702000000, 867000, 967000),
>> +       OPP(1001000000, 927000, 1027000),
>> +       OPP(1209000000, 968000, 1068000),
>> +       OPP(1404000000, 1007000, 1107000),
>> +       OPP(1612000000, 1049000, 1149000),
>> +       OPP(1807000000, 1089000, 1150000),
>> +       OPP(1989000000, 1125000, 1150000),
>> +};
>
> We should sort out the OPP bindings if we need to sort out the OPP
> bindings. We can't remove these once they're in without causing pain for
> everyone with an old DTB.

So even we have a new OPP binding to describe the OPP, we have to
leave these table as they are for backward compatibility?

Best Regards,
Pi-Cheng

>
> Mark.


From pi-cheng.chen at linaro.org  Fri Apr 24 00:09:23 2015
From: pi-cheng.chen at linaro.org (Pi-Cheng Chen)
Date: Fri, 24 Apr 2015 15:09:23 +0800
Subject: [PATCH 2/2] ARM64: mt8173: dts Add MT8173 cpufreq driver support
In-Reply-To: <20150423125358.GA29702@leverpostej>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-3-git-send-email-pi-cheng.chen@linaro.org>
 <20150423125358.GA29702@leverpostej>
Message-ID: <CALx668UiU73HAwGdezrXDxTm_4_N0HUJQFYa1E_Guv_j3NG00g@mail.gmail.com>

Hi Mark,

Thanks for reviewing.

On Thu, Apr 23, 2015 at 8:53 PM, Mark Rutland <mark.rutland at arm.com> wrote:
> On Mon, Apr 20, 2015 at 10:27:27AM +0100, pi-cheng.chen wrote:
>> This patch adds voltage supplies and clocks used by MT8173 cpufreq driver.
>>
>> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
>
> This series has no bindings for these properties.

Will add documents for these.

>
>> ---
>>  arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 9 +++++++++
>>  arch/arm64/boot/dts/mediatek/mt8173.dtsi    | 6 ++++++
>>  2 files changed, 15 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
>> index 96e141c..7a00cfe 100644
>> --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
>> +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
>> @@ -330,3 +330,12 @@
>>       status = "okay";
>>       clock-frequency = <100000>;
>>  };
>> +
>> +&cpu0 {
>> +     proc-supply = <&mt6397_vpca15_reg>;
>> +};
>> +
>> +&cpu2 {
>> +     proc-supply = <&da9211_vcpu_reg>;
>> +     sram-supply = <&mt6397_vsramca7_reg>;
>> +};
>
>
> Why do only two CPUs have these properties, and why does one need an
> sram-supply?

For better description of hardware, I think putting these properties in all CPUs
share the same supplies is logical.

For each cluster of MT8173, we have both PROC and SRAM supplies. But only
on one cluster (cpu2 and cpu3) we need to control both voltage supplies. The
SRAM supply on cpu0 cluster is controlled by hardware automatically. Therefore
I put sram-supply only on cpu2. For better description of hardware, it
might be a
good idea to put the SRAM supply in cpu0 also though we don't use it in the
driver, right?

>
>> diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> index d9cc84e..b8a5454 100644
>> --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> @@ -51,6 +51,9 @@
>>                       device_type = "cpu";
>>                       compatible = "arm,cortex-a53";
>>                       reg = <0x000>;
>> +                     clocks = <&infracfg INFRA_CA53SEL>,
>> +                              <&apmixedsys APMIXED_MAINPLL>;
>> +                     clock-names = "cpu", "intermediate";
>>               };
>>
>>               cpu1: cpu at 1 {
>> @@ -65,6 +68,9 @@
>>                       compatible = "arm,cortex-a57";
>>                       reg = <0x100>;
>>                       enable-method = "psci";
>> +                     clocks = <&infracfg INFRA_CA57SEL>,
>> +                              <&apmixedsys APMIXED_MAINPLL>;
>> +                     clock-names = "cpu", "intermediate";
>>               };
>
> We should really describe this information per-cpu rather than assuming
> that it's the same for siblings. Arbitrarily making one CPU in each
> cluster (or other arbitrary grouping) special for the binding is silly.

Yes, I agree with you and same above. I did these because most of the
platforms in kernel did these. So should I do it the way you suggest?

Thanks.

Best Regards,
Pi-Cheng

>
> Mark.


From matthias.bgg at gmail.com  Fri Apr 24 00:58:08 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 24 Apr 2015 09:58:08 +0200
Subject: [PATCH 4/4] ARM: dts: mediatek mt8135: Use real UART clocks
In-Reply-To: <1429780875-29096-5-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
 <1429780875-29096-5-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeKoxAdW3VdrF229VAm+eB8Rku=_QF9bu-nCXfj+T=dMvg@mail.gmail.com>

2015-04-23 11:21 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> We used to provide dummy clocks for the UART. Now that we have
> common clock support we can provide the real clocks to the UART.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  arch/arm/boot/dts/mt8135.dtsi | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
> index b0f20fc..4d1ddd9 100644
> --- a/arch/arm/boot/dts/mt8135.dtsi
> +++ b/arch/arm/boot/dts/mt8135.dtsi
> @@ -180,7 +180,8 @@
>                         compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart";
>                         reg = <0 0x11006000 0 0x400>;
>                         interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
> -                       clocks = <&uart_clk>;
> +                       clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
> +                       clock-names = "baud", "bus";
>                         status = "disabled";
>                 };

We can delete the dummy uart_clk, as it is not needed any more.

-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Fri Apr 24 03:28:33 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 24 Apr 2015 12:28:33 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>

2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
> which is the correct function when a struct device * is available. Also
> since it's a devm function we can drop the calls to clk_put(). While at
> it also fix a wrong debug message.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
> index 7a11fac..c6901dc 100644
> --- a/drivers/tty/serial/8250/8250_mtk.c
> +++ b/drivers/tty/serial/8250/8250_mtk.c
> @@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
>                            struct mtk8250_data *data)
>  {
>         int err;
> -       struct device_node *np = pdev->dev.of_node;
>
> -       data->uart_clk = of_clk_get(np, 0);
> +       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
>         if (IS_ERR(data->uart_clk)) {
> -               dev_warn(&pdev->dev, "Can't get timer clock\n");
> +               dev_warn(&pdev->dev, "Can't get uart clock\n");
>                 return PTR_ERR(data->uart_clk);
>         }
>
>         err = clk_prepare_enable(data->uart_clk);
>         if (err) {
>                 dev_warn(&pdev->dev, "Can't prepare clock\n");
> -               clk_put(data->uart_clk);
>                 return err;
>         }
>         p->uartclk = clk_get_rate(data->uart_clk);
> @@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
>         serial8250_unregister_port(data->line);
>         if (!IS_ERR(data->uart_clk)) {
>                 clk_disable_unprepare(data->uart_clk);
> -               clk_put(data->uart_clk);
>         }

Please delete the braces.


-- 
motzblog.wordpress.com


From s.hauer at pengutronix.de  Fri Apr 24 03:31:51 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 24 Apr 2015 12:31:51 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
 <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>
Message-ID: <20150424103151.GP6325@pengutronix.de>

On Fri, Apr 24, 2015 at 12:28:33PM +0200, Matthias Brugger wrote:
> 2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> > Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
> > which is the correct function when a struct device * is available. Also
> > since it's a devm function we can drop the calls to clk_put(). While at
> > it also fix a wrong debug message.
> >
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> >  drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
> >  1 file changed, 2 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
> > index 7a11fac..c6901dc 100644
> > --- a/drivers/tty/serial/8250/8250_mtk.c
> > +++ b/drivers/tty/serial/8250/8250_mtk.c
> > @@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
> >                            struct mtk8250_data *data)
> >  {
> >         int err;
> > -       struct device_node *np = pdev->dev.of_node;
> >
> > -       data->uart_clk = of_clk_get(np, 0);
> > +       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
> >         if (IS_ERR(data->uart_clk)) {
> > -               dev_warn(&pdev->dev, "Can't get timer clock\n");
> > +               dev_warn(&pdev->dev, "Can't get uart clock\n");
> >                 return PTR_ERR(data->uart_clk);
> >         }
> >
> >         err = clk_prepare_enable(data->uart_clk);
> >         if (err) {
> >                 dev_warn(&pdev->dev, "Can't prepare clock\n");
> > -               clk_put(data->uart_clk);
> >                 return err;
> >         }
> >         p->uartclk = clk_get_rate(data->uart_clk);
> > @@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
> >         serial8250_unregister_port(data->line);
> >         if (!IS_ERR(data->uart_clk)) {
> >                 clk_disable_unprepare(data->uart_clk);
> > -               clk_put(data->uart_clk);
> >         }
> 
> Please delete the braces.

The if() is removed completly in the next patch anyway.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Fri Apr 24 03:53:08 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 24 Apr 2015 12:53:08 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <20150424103151.GP6325@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
 <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>
 <20150424103151.GP6325@pengutronix.de>
Message-ID: <CABuKBeLEui7ufMZ1=wz2kss4Q8yuK2VYt=wDWam6ZkCfd1G+7Q@mail.gmail.com>

2015-04-24 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Fri, Apr 24, 2015 at 12:28:33PM +0200, Matthias Brugger wrote:
>> 2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> > Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
>> > which is the correct function when a struct device * is available. Also
>> > since it's a devm function we can drop the calls to clk_put(). While at
>> > it also fix a wrong debug message.
>> >
>> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>> > ---
>> >  drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
>> >  1 file changed, 2 insertions(+), 5 deletions(-)
>> >
>> > diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
>> > index 7a11fac..c6901dc 100644
>> > --- a/drivers/tty/serial/8250/8250_mtk.c
>> > +++ b/drivers/tty/serial/8250/8250_mtk.c
>> > @@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
>> >                            struct mtk8250_data *data)
>> >  {
>> >         int err;
>> > -       struct device_node *np = pdev->dev.of_node;
>> >
>> > -       data->uart_clk = of_clk_get(np, 0);
>> > +       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
>> >         if (IS_ERR(data->uart_clk)) {
>> > -               dev_warn(&pdev->dev, "Can't get timer clock\n");
>> > +               dev_warn(&pdev->dev, "Can't get uart clock\n");
>> >                 return PTR_ERR(data->uart_clk);
>> >         }
>> >
>> >         err = clk_prepare_enable(data->uart_clk);
>> >         if (err) {
>> >                 dev_warn(&pdev->dev, "Can't prepare clock\n");
>> > -               clk_put(data->uart_clk);
>> >                 return err;
>> >         }
>> >         p->uartclk = clk_get_rate(data->uart_clk);
>> > @@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
>> >         serial8250_unregister_port(data->line);
>> >         if (!IS_ERR(data->uart_clk)) {
>> >                 clk_disable_unprepare(data->uart_clk);
>> > -               clk_put(data->uart_clk);
>> >         }
>>
>> Please delete the braces.
>
> The if() is removed completly in the next patch anyway.

You are right. I propose to merge patch 2 and 3, so you get a clean code.
On the way, can you have a look on the commit message? For me it is
not clear what you want to say.

Cheers,
Matthias

-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Fri Apr 24 03:56:40 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 24 Apr 2015 12:56:40 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <CABuKBeLEui7ufMZ1=wz2kss4Q8yuK2VYt=wDWam6ZkCfd1G+7Q@mail.gmail.com>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
 <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>
 <20150424103151.GP6325@pengutronix.de>
 <CABuKBeLEui7ufMZ1=wz2kss4Q8yuK2VYt=wDWam6ZkCfd1G+7Q@mail.gmail.com>
Message-ID: <CABuKBeJHABA6gowf97kKKfnBhh9rNmzexuMvb3z1VjFuq53NeA@mail.gmail.com>

2015-04-24 12:53 GMT+02:00 Matthias Brugger <matthias.bgg at gmail.com>:
> 2015-04-24 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>> On Fri, Apr 24, 2015 at 12:28:33PM +0200, Matthias Brugger wrote:
>>> 2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
>>> > Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
>>> > which is the correct function when a struct device * is available. Also
>>> > since it's a devm function we can drop the calls to clk_put(). While at
>>> > it also fix a wrong debug message.
>>> >
>>> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>>> > ---
>>> >  drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
>>> >  1 file changed, 2 insertions(+), 5 deletions(-)
>>> >
>>> > diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
>>> > index 7a11fac..c6901dc 100644
>>> > --- a/drivers/tty/serial/8250/8250_mtk.c
>>> > +++ b/drivers/tty/serial/8250/8250_mtk.c
>>> > @@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
>>> >                            struct mtk8250_data *data)
>>> >  {
>>> >         int err;
>>> > -       struct device_node *np = pdev->dev.of_node;
>>> >
>>> > -       data->uart_clk = of_clk_get(np, 0);
>>> > +       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
>>> >         if (IS_ERR(data->uart_clk)) {
>>> > -               dev_warn(&pdev->dev, "Can't get timer clock\n");
>>> > +               dev_warn(&pdev->dev, "Can't get uart clock\n");
>>> >                 return PTR_ERR(data->uart_clk);
>>> >         }
>>> >
>>> >         err = clk_prepare_enable(data->uart_clk);
>>> >         if (err) {
>>> >                 dev_warn(&pdev->dev, "Can't prepare clock\n");
>>> > -               clk_put(data->uart_clk);
>>> >                 return err;
>>> >         }
>>> >         p->uartclk = clk_get_rate(data->uart_clk);
>>> > @@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
>>> >         serial8250_unregister_port(data->line);
>>> >         if (!IS_ERR(data->uart_clk)) {
>>> >                 clk_disable_unprepare(data->uart_clk);
>>> > -               clk_put(data->uart_clk);
>>> >         }
>>>
>>> Please delete the braces.
>>
>> The if() is removed completly in the next patch anyway.
>
> You are right. I propose to merge patch 2 and 3, so you get a clean code.
> On the way, can you have a look on the commit message? For me it is
> not clear what you want to say.

Actually I meant patch 1 and 2 of the series. Sorry for the confusion.


-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Fri Apr 24 04:18:07 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 24 Apr 2015 13:18:07 +0200
Subject: [PATCH 4/4] tty: serial: 8250_mtk: Add support for bus clock
In-Reply-To: <1429779066-21406-5-git-send-email-s.hauer@pengutronix.de>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-5-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBe+ebskWHVRtcfei9hZVvt5oHA0wij0WuLCkYqJo0Hzm=Q@mail.gmail.com>

2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> The mtk 8250 needs two clocks, one for providing the baudrate and
> one that needs to be enabled for register accesses. The latter has
> not been supported, this patch adds support for it. It is optional
> for now since not all SoCs provide a bus clock.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  Documentation/devicetree/bindings/serial/mtk-uart.txt |  9 +++++++--
>  drivers/tty/serial/8250/8250_mtk.c                    | 14 +++++++++++++-
>  2 files changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
> index 4415226..369b5c3 100644
> --- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
> +++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
> @@ -14,7 +14,11 @@ Required properties:
>
>  - interrupts: A single interrupt specifier.
>
> -- clocks: Clock driving the hardware.
> +- clocks : Must contain an entry for each entry in clock-names.
> +  See ../clocks/clock-bindings.txt for details.
> +- clock-names:
> +  - "baud": The clock the baudrate is derived from
> +  - "bus": The bus clock for register accesses (optional)
>
>  Example:
>
> @@ -22,5 +26,6 @@ Example:
>                 compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
>                 reg = <0x11006000 0x400>;
>                 interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
> -               clocks = <&uart_clk>;
> +               clocks = <&uart_clk>, <&bus_clk>;
> +               clock-names = "baud", "bus";
>         };
> diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
> index 2f28bd0..20c27f0 100644
> --- a/drivers/tty/serial/8250/8250_mtk.c
> +++ b/drivers/tty/serial/8250/8250_mtk.c
> @@ -34,6 +34,7 @@
>  struct mtk8250_data {
>         int                     line;
>         struct clk              *uart_clk;
> +       struct clk              *bus_clk;
>  };
>
>  static void
> @@ -120,6 +121,7 @@ static int mtk8250_runtime_suspend(struct device *dev)
>         struct mtk8250_data *data = dev_get_drvdata(dev);
>
>         clk_disable_unprepare(data->uart_clk);
> +       clk_disable_unprepare(data->bus_clk);
>
>         return 0;
>  }
> @@ -135,6 +137,12 @@ static int mtk8250_runtime_resume(struct device *dev)
>                 return err;
>         }
>
> +       err = clk_prepare_enable(data->bus_clk);
> +       if (err) {
> +               dev_warn(dev, "Can't enable bus clock\n");
> +               return err;
> +       }
> +
>         return 0;
>  }
>
> @@ -153,7 +161,7 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
>  static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
>                            struct mtk8250_data *data)
>  {
> -       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
> +       data->uart_clk = devm_clk_get(&pdev->dev, "baud");
>         if (IS_ERR(data->uart_clk)) {
>                 dev_warn(&pdev->dev, "Can't get uart clock\n");
>                 return PTR_ERR(data->uart_clk);
> @@ -161,6 +169,10 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
>
>         p->uartclk = clk_get_rate(data->uart_clk);
>
> +       data->bus_clk = devm_clk_get(&pdev->dev, "bus");
> +       if (IS_ERR(data->bus_clk))
> +               data->bus_clk = NULL;
> +

We have to take into account the old DTS definition. This means, that
if devm_clk_get(&pdev->dev, "baud") fails, we have to look for
devm_clk_get(&pdev->dev, NULL).
Only in the case I when clock "baud" does exist, do we check for clock
"bus". Does this make sense?

The backwards compatibility should be reflected in the bindings
documentation as well.

Cheers,
Matthias

-- 
motzblog.wordpress.com


From s.hauer at pengutronix.de  Fri Apr 24 05:55:21 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 24 Apr 2015 14:55:21 +0200
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <CALx668VsT60+kx7o-ZM5Wxk7Nn-rXS21O5SDYr++EeY-zEJ6ew@mail.gmail.com>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150423120152.GM6325@pengutronix.de>
 <CALx668VsT60+kx7o-ZM5Wxk7Nn-rXS21O5SDYr++EeY-zEJ6ew@mail.gmail.com>
Message-ID: <20150424125521.GU6325@pengutronix.de>

On Fri, Apr 24, 2015 at 02:46:25PM +0800, Pi-Cheng Chen wrote:
> Hi Sascha,
> 
> Thanks for reviewing.
> 
> On Thu, Apr 23, 2015 at 8:01 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
> >> This patch implements MT8173 specific cpufreq driver with OPP table defined
> >> in the driver code.
> >>
> >> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
> >> ---
> >>  drivers/cpufreq/Kconfig.arm      |   6 +
> >>  drivers/cpufreq/Makefile         |   1 +
> >>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 516 insertions(+)
> >>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
> >>
> >> +static int mtk_cpufreq_voltage_trace(struct cpu_dvfs_info *info,
> >> +                                  struct mtk_cpu_opp *opp)
> >> +{
> >> +     struct regulator *proc_reg = info->proc_reg;
> >> +     struct regulator *sram_reg = info->sram_reg;
> >> +     int old_vproc, new_vproc, old_vsram, new_vsram, vsram, vproc, ret;
> >> +
> >> +     old_vproc = regulator_get_voltage(proc_reg);
> >> +     old_vsram = regulator_get_voltage(sram_reg);
> >> +
> >> +     new_vproc = opp->vproc;
> >> +     new_vsram = opp->vsram;
> >> +
> >> +     /*
> >> +      * In the case the voltage is going to be scaled up, Vsram and Vproc
> >> +      * need to be scaled up step by step. In each step, Vsram needs to be
> >> +      * set to (Vproc + 200mV) first, then Vproc is set to (Vsram - 100mV).
> >> +      * Repeat the step until Vsram and Vproc are set to target voltage.
> >> +      */
> >> +     if (old_vproc < new_vproc) {
> >> +next_up_step:
> >> +             old_vsram = regulator_get_voltage(sram_reg);
> >> +
> >> +             vsram = (new_vsram - old_vproc < MAX_VOLT_SHIFT) ?
> >> +                     new_vsram : old_vproc + MAX_VOLT_SHIFT;
> >> +             vsram = get_regulator_voltage_floor(sram_reg, vsram);
> >> +
> >> +             ret = regulator_set_voltage(sram_reg, vsram, vsram);
> >> +             if (ret)
> >> +                     return ret;
> >
> > This introspecting the regulators for possible voltages looks hacky and
> > unnecessary. regulator_set_voltage() can be passed minimum and maximum
> > values, why don't you use it to increase the voltage within sensible
> > limit, like
> >
> >         regulator_set_voltage(sram_reg, old_vsram + 100000, old_vsram + 200000);
> >
> > or similar?
> 
> I am sorry I don't understand how could I do it. Would you elaborate?

You try to set the OPPs to the exact voltages, then next use functions
to determine the next exact higher voltage and set the regulator voltage
to an exact value. Instead of doing this you can let the ability to
specify a voltage range work for you, something like:

	int tolerance = 50000;

	while (vproc < new_vproc) {
		int next = min(new_vproc - vproc, 200000);
		int next_sram = next + 100000;

		regulator_set_voltage(sram_reg, next_sram - tolerance, next_sram + tolerance);
		regulator_set_voltage(vproc_reg, next - tolerance, next + tolerance);
		vproc = regulator_get_voltage(vproc_reg);
	}

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr 26 23:33:01 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:33:01 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <CABuKBeLEui7ufMZ1=wz2kss4Q8yuK2VYt=wDWam6ZkCfd1G+7Q@mail.gmail.com>
References: <1429779066-21406-1-git-send-email-s.hauer@pengutronix.de>
 <1429779066-21406-2-git-send-email-s.hauer@pengutronix.de>
 <CABuKBe+bACg_5uDQc3BF4BaBUG1-CQ3mH199o3nMsaMfH3ad3w@mail.gmail.com>
 <20150424103151.GP6325@pengutronix.de>
 <CABuKBeLEui7ufMZ1=wz2kss4Q8yuK2VYt=wDWam6ZkCfd1G+7Q@mail.gmail.com>
Message-ID: <20150427063301.GW6325@pengutronix.de>

On Fri, Apr 24, 2015 at 12:53:08PM +0200, Matthias Brugger wrote:
> 2015-04-24 12:31 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> > On Fri, Apr 24, 2015 at 12:28:33PM +0200, Matthias Brugger wrote:
> >> 2015-04-23 10:51 GMT+02:00 Sascha Hauer <s.hauer at pengutronix.de>:
> >> > Just because of_clk_get() doesn't mean it should be used. Use devm_clk_get
> >> > which is the correct function when a struct device * is available. Also
> >> > since it's a devm function we can drop the calls to clk_put(). While at
> >> > it also fix a wrong debug message.
> >> >
> >> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> >> > ---
> >> >  drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
> >> >  1 file changed, 2 insertions(+), 5 deletions(-)
> >> >
> >> > diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
> >> > index 7a11fac..c6901dc 100644
> >> > --- a/drivers/tty/serial/8250/8250_mtk.c
> >> > +++ b/drivers/tty/serial/8250/8250_mtk.c
> >> > @@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
> >> >                            struct mtk8250_data *data)
> >> >  {
> >> >         int err;
> >> > -       struct device_node *np = pdev->dev.of_node;
> >> >
> >> > -       data->uart_clk = of_clk_get(np, 0);
> >> > +       data->uart_clk = devm_clk_get(&pdev->dev, NULL);
> >> >         if (IS_ERR(data->uart_clk)) {
> >> > -               dev_warn(&pdev->dev, "Can't get timer clock\n");
> >> > +               dev_warn(&pdev->dev, "Can't get uart clock\n");
> >> >                 return PTR_ERR(data->uart_clk);
> >> >         }
> >> >
> >> >         err = clk_prepare_enable(data->uart_clk);
> >> >         if (err) {
> >> >                 dev_warn(&pdev->dev, "Can't prepare clock\n");
> >> > -               clk_put(data->uart_clk);
> >> >                 return err;
> >> >         }
> >> >         p->uartclk = clk_get_rate(data->uart_clk);
> >> > @@ -216,7 +214,6 @@ static int mtk8250_remove(struct platform_device *pdev)
> >> >         serial8250_unregister_port(data->line);
> >> >         if (!IS_ERR(data->uart_clk)) {
> >> >                 clk_disable_unprepare(data->uart_clk);
> >> > -               clk_put(data->uart_clk);
> >> >         }
> >>
> >> Please delete the braces.
> >
> > The if() is removed completly in the next patch anyway.
> 
> You are right. I propose to merge patch 2 and 3, so you get a clean code.

Patches 1 and 2 are different topics, I see no reason merging them. I
changed the order of the two patches, maybe this makes it better
readable.

> On the way, can you have a look on the commit message? For me it is
> not clear what you want to say.

Changed to:

    When a struct device * is present clk_get should be used rather
    than of_clk_get. Use the devm variant of this function to be able to
    drop the clk_put in the error and remove pathes. While at it fix
    a wrong error message.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr 26 23:49:53 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:49:53 +0200
Subject: [PATCH v2] tty: serial: 8250_mtk: Add support for second clock
Message-ID: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>

The following changes since commit b787f68c36d49bb1d9236f403813641efa74a031:

  Linux 4.1-rc1 (2015-04-26 17:59:10 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/sha/linux-2.6.git tags/v4.1-mtk-uart-clk-v2

for you to fetch changes up to 02e3f747bea47f6c02dc3f52e40869ea8ce5342a:

  tty: serial: 8250_mtk: Add support for bus clock (2015-04-27 08:39:06 +0200)

----------------------------------------------------------------
This series adds support for the second clock on the Mediatek UART.
This is necessary for SoCs needing a bus clock to be enabled before
the UART can be accessed.

Changes since v1:
- keep support old binding with unnamed clk
- hopefully clarify commit message
- do not leak in if() with unnecessary braces.

----------------------------------------------------------------
Sascha Hauer (4):
      tty: serial: 8250_mtk: remove unnecessary test
      tty: serial: 8250_mtk: Use devm_clk_get
      tty: serial: 8250_mtk: use pm_runtime callbacks for enabling
      tty: serial: 8250_mtk: Add support for bus clock

 .../devicetree/bindings/serial/mtk-uart.txt        |  12 ++-
 drivers/tty/serial/8250/8250_mtk.c                 | 104 ++++++++++++---------
 2 files changed, 70 insertions(+), 46 deletions(-)


From s.hauer at pengutronix.de  Sun Apr 26 23:49:54 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:49:54 +0200
Subject: [PATCH 1/4] tty: serial: 8250_mtk: remove unnecessary test
In-Reply-To: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
References: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430117397-13517-2-git-send-email-s.hauer@pengutronix.de>

When the driver has probed successfully the clk pointer is always valid,
so no need to test for it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 7a11fac..1297827 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -214,10 +214,8 @@ static int mtk8250_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 
 	serial8250_unregister_port(data->line);
-	if (!IS_ERR(data->uart_clk)) {
-		clk_disable_unprepare(data->uart_clk);
-		clk_put(data->uart_clk);
-	}
+	clk_disable_unprepare(data->uart_clk);
+	clk_put(data->uart_clk);
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
@@ -249,8 +247,7 @@ static int mtk8250_runtime_suspend(struct device *dev)
 {
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
-	if (!IS_ERR(data->uart_clk))
-		clk_disable_unprepare(data->uart_clk);
+	clk_disable_unprepare(data->uart_clk);
 
 	return 0;
 }
@@ -259,8 +256,7 @@ static int mtk8250_runtime_resume(struct device *dev)
 {
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
-	if (!IS_ERR(data->uart_clk))
-		clk_prepare_enable(data->uart_clk);
+	clk_prepare_enable(data->uart_clk);
 
 	return 0;
 }
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Apr 26 23:49:56 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:49:56 +0200
Subject: [PATCH 3/4] tty: serial: 8250_mtk: use pm_runtime callbacks for
 enabling
In-Reply-To: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
References: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430117397-13517-4-git-send-email-s.hauer@pengutronix.de>

The pm_runtime callbacks already enable and disable the device.
Use them in probe() and remove() instead of duplicating the
code. This allows us to concentrate more code for enabling/disabling
the UART in a single place.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 69 ++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index bcfaa8dc..2f28bd0 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -115,6 +115,29 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
 		tty_termios_encode_baud_rate(termios, baud, baud);
 }
 
+static int mtk8250_runtime_suspend(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(data->uart_clk);
+
+	return 0;
+}
+
+static int mtk8250_runtime_resume(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+	int err;
+
+	err = clk_prepare_enable(data->uart_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable clock\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static void
 mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 {
@@ -130,19 +153,12 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
-	int err;
-
 	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(data->uart_clk)) {
 		dev_warn(&pdev->dev, "Can't get uart clock\n");
 		return PTR_ERR(data->uart_clk);
 	}
 
-	err = clk_prepare_enable(data->uart_clk);
-	if (err) {
-		dev_warn(&pdev->dev, "Can't prepare clock\n");
-		return err;
-	}
 	p->uartclk = clk_get_rate(data->uart_clk);
 
 	return 0;
@@ -193,14 +209,18 @@ static int mtk8250_probe(struct platform_device *pdev)
 	writel(0x0, uart.port.membase +
 			(MTK_UART_RATE_FIX << uart.port.regshift));
 
-	data->line = serial8250_register_8250_port(&uart);
-	if (data->line < 0)
-		return data->line;
-
 	platform_set_drvdata(pdev, data);
 
-	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		err = mtk8250_runtime_resume(&pdev->dev);
+		if (err)
+			return err;
+	}
+
+	data->line = serial8250_register_8250_port(&uart);
+	if (data->line < 0)
+		return data->line;
 
 	return 0;
 }
@@ -212,10 +232,13 @@ static int mtk8250_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 
 	serial8250_unregister_port(data->line);
-	clk_disable_unprepare(data->uart_clk);
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
+
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		mtk8250_runtime_suspend(&pdev->dev);
+
 	return 0;
 }
 
@@ -239,26 +262,6 @@ static int mtk8250_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-#ifdef CONFIG_PM
-static int mtk8250_runtime_suspend(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	clk_disable_unprepare(data->uart_clk);
-
-	return 0;
-}
-
-static int mtk8250_runtime_resume(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	clk_prepare_enable(data->uart_clk);
-
-	return 0;
-}
-#endif
-
 static const struct dev_pm_ops mtk8250_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume)
 	SET_RUNTIME_PM_OPS(mtk8250_runtime_suspend, mtk8250_runtime_resume,
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Apr 26 23:49:57 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:49:57 +0200
Subject: [PATCH 4/4] tty: serial: 8250_mtk: Add support for bus clock
In-Reply-To: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
References: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430117397-13517-5-git-send-email-s.hauer@pengutronix.de>

The mtk 8250 needs two clocks, one for providing the baudrate and
one that needs to be enabled for register accesses. The latter has
not been supported, this patch adds support for it. It is optional
for now since not all SoCs provide a bus clock.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 .../devicetree/bindings/serial/mtk-uart.txt        | 12 ++++++++--
 drivers/tty/serial/8250/8250_mtk.c                 | 28 ++++++++++++++++++----
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 4415226..8d63f1d 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -14,7 +14,14 @@ Required properties:
 
 - interrupts: A single interrupt specifier.
 
-- clocks: Clock driving the hardware.
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names:
+  - "baud": The clock the baudrate is derived from
+  - "bus": The bus clock for register accesses (optional)
+
+For compatibility with older device trees an unnamed clock is used for the
+baud clock if the baudclk does not exist. Do not use this for new designs.
 
 Example:
 
@@ -22,5 +29,6 @@ Example:
 		compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
 		reg = <0x11006000 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&uart_clk>, <&bus_clk>;
+		clock-names = "baud", "bus";
 	};
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 2f28bd0..8eb3876 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -34,6 +34,7 @@
 struct mtk8250_data {
 	int			line;
 	struct clk		*uart_clk;
+	struct clk		*bus_clk;
 };
 
 static void
@@ -120,6 +121,7 @@ static int mtk8250_runtime_suspend(struct device *dev)
 	struct mtk8250_data *data = dev_get_drvdata(dev);
 
 	clk_disable_unprepare(data->uart_clk);
+	clk_disable_unprepare(data->bus_clk);
 
 	return 0;
 }
@@ -135,6 +137,12 @@ static int mtk8250_runtime_resume(struct device *dev)
 		return err;
 	}
 
+	err = clk_prepare_enable(data->bus_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable bus clock\n");
+		return err;
+	}
+
 	return 0;
 }
 
@@ -153,13 +161,24 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
-	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
+	data->uart_clk = devm_clk_get(&pdev->dev, "baud");
 	if (IS_ERR(data->uart_clk)) {
-		dev_warn(&pdev->dev, "Can't get uart clock\n");
-		return PTR_ERR(data->uart_clk);
+		/*
+		 * For compatibility with older device trees try unnamed
+		 * clk when no baud clk can be found.
+		 */
+		data->uart_clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(data->uart_clk)) {
+			dev_warn(&pdev->dev, "Can't get uart clock\n");
+			return PTR_ERR(data->uart_clk);
+		}
+
+		return 0;
 	}
 
-	p->uartclk = clk_get_rate(data->uart_clk);
+	data->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(data->bus_clk))
+		return PTR_ERR(data->bus_clk);
 
 	return 0;
 }
@@ -204,6 +223,7 @@ static int mtk8250_probe(struct platform_device *pdev)
 	uart.port.regshift = 2;
 	uart.port.private_data = data;
 	uart.port.set_termios = mtk8250_set_termios;
+	uart.port.uartclk = clk_get_rate(data->uart_clk);
 
 	/* Disable Rate Fix function */
 	writel(0x0, uart.port.membase +
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Apr 26 23:49:55 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 27 Apr 2015 08:49:55 +0200
Subject: [PATCH 2/4] tty: serial: 8250_mtk: Use devm_clk_get
In-Reply-To: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
References: <1430117397-13517-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430117397-13517-3-git-send-email-s.hauer@pengutronix.de>

When a struct device * is present clk_get should be used rather
than of_clk_get. Use the devm variant of this function to be able to
drop the clk_put in the error and remove pathes. While at it fix
a wrong error message.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/tty/serial/8250/8250_mtk.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 1297827..bcfaa8dc 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -131,18 +131,16 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 {
 	int err;
-	struct device_node *np = pdev->dev.of_node;
 
-	data->uart_clk = of_clk_get(np, 0);
+	data->uart_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(data->uart_clk)) {
-		dev_warn(&pdev->dev, "Can't get timer clock\n");
+		dev_warn(&pdev->dev, "Can't get uart clock\n");
 		return PTR_ERR(data->uart_clk);
 	}
 
 	err = clk_prepare_enable(data->uart_clk);
 	if (err) {
 		dev_warn(&pdev->dev, "Can't prepare clock\n");
-		clk_put(data->uart_clk);
 		return err;
 	}
 	p->uartclk = clk_get_rate(data->uart_clk);
@@ -215,7 +213,6 @@ static int mtk8250_remove(struct platform_device *pdev)
 
 	serial8250_unregister_port(data->line);
 	clk_disable_unprepare(data->uart_clk);
-	clk_put(data->uart_clk);
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
-- 
2.1.4



From k.kozlowski.k at gmail.com  Mon Apr 27 05:54:23 2015
From: k.kozlowski.k at gmail.com (Krzysztof Kozlowski)
Date: Mon, 27 Apr 2015 21:54:23 +0900
Subject: [PATCH 1/2] genirq: MSI: Constify irq_domain_ops
Message-ID: <1430139264-4362-1-git-send-email-k.kozlowski.k@gmail.com>

The irq_domain_ops are not modified. The irqdomain core code accepts
pointer to a const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski.k at gmail.com>
---
 kernel/irq/msi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 474de5cb394d..7bf1f1bbb7fa 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -124,7 +124,7 @@ static void msi_domain_free(struct irq_domain *domain, unsigned int virq,
 	irq_domain_free_irqs_top(domain, virq, nr_irqs);
 }
 
-static struct irq_domain_ops msi_domain_ops = {
+static const struct irq_domain_ops msi_domain_ops = {
 	.alloc		= msi_domain_alloc,
 	.free		= msi_domain_free,
 	.activate	= msi_domain_activate,
-- 
2.1.0



From k.kozlowski.k at gmail.com  Mon Apr 27 05:54:24 2015
From: k.kozlowski.k at gmail.com (Krzysztof Kozlowski)
Date: Mon, 27 Apr 2015 21:54:24 +0900
Subject: [PATCH 2/2] irqchip: Constify irq_domain_ops
In-Reply-To: <1430139264-4362-1-git-send-email-k.kozlowski.k@gmail.com>
References: <1430139264-4362-1-git-send-email-k.kozlowski.k@gmail.com>
Message-ID: <1430139264-4362-2-git-send-email-k.kozlowski.k@gmail.com>

The irq_domain_ops are not modified by the driver and the irqdomain core
code accepts pointer to a const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski.k at gmail.com>
---
 drivers/irqchip/exynos-combiner.c         | 2 +-
 drivers/irqchip/irq-armada-370-xp.c       | 2 +-
 drivers/irqchip/irq-bcm2835.c             | 2 +-
 drivers/irqchip/irq-keystone.c            | 2 +-
 drivers/irqchip/irq-mips-gic.c            | 2 +-
 drivers/irqchip/irq-mtk-sysirq.c          | 2 +-
 drivers/irqchip/irq-mxs.c                 | 2 +-
 drivers/irqchip/irq-renesas-intc-irqpin.c | 2 +-
 drivers/irqchip/irq-renesas-irqc.c        | 2 +-
 drivers/irqchip/irq-s3c24xx.c             | 4 ++--
 drivers/irqchip/irq-sun4i.c               | 2 +-
 drivers/irqchip/irq-versatile-fpga.c      | 2 +-
 drivers/irqchip/irq-vic.c                 | 2 +-
 drivers/irqchip/irq-vt8500.c              | 2 +-
 14 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index 5945223b73fa..a57a3a1f339f 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -164,7 +164,7 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-static struct irq_domain_ops combiner_irq_domain_ops = {
+static const struct irq_domain_ops combiner_irq_domain_ops = {
 	.xlate	= combiner_irq_domain_xlate,
 	.map	= combiner_irq_domain_map,
 };
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index daccc8bdbb42..0d3b0fe2f175 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -409,7 +409,7 @@ static struct notifier_block mpic_cascaded_cpu_notifier = {
 };
 #endif /* CONFIG_SMP */
 
-static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
+static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
 	.map = armada_370_xp_mpic_irq_map,
 	.xlate = irq_domain_xlate_onecell,
 };
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index 5916d6cdafa1..e68c3b60a681 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -135,7 +135,7 @@ static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
 	return 0;
 }
 
-static struct irq_domain_ops armctrl_ops = {
+static const struct irq_domain_ops armctrl_ops = {
 	.xlate = armctrl_xlate
 };
 
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index 78e8b3ce5252..5dc61655055a 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -131,7 +131,7 @@ static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops keystone_irq_ops = {
+static const struct irq_domain_ops keystone_irq_ops = {
 	.map	= keystone_irq_map,
 	.xlate	= irq_domain_xlate_onecell,
 };
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 57f09cb54464..44d2d106e818 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -739,7 +739,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
 	return 0;
 }
 
-static struct irq_domain_ops gic_irq_domain_ops = {
+static const struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.xlate = gic_irq_domain_xlate,
 };
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index eaf0a710e98a..04de2d4ca70f 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -111,7 +111,7 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
 }
 
-static struct irq_domain_ops sysirq_domain_ops = {
+static const struct irq_domain_ops sysirq_domain_ops = {
 	.xlate = mtk_sysirq_domain_xlate,
 	.alloc = mtk_sysirq_domain_alloc,
 	.free = irq_domain_free_irqs_common,
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index e4acf1e3f8e3..04bf97b289cf 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -90,7 +90,7 @@ static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops icoll_irq_domain_ops = {
+static const struct irq_domain_ops icoll_irq_domain_ops = {
 	.map = icoll_irq_domain_map,
 	.xlate = irq_domain_xlate_onecell,
 };
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 9a0767b9c89d..0670ab4e3897 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -347,7 +347,7 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
+static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
 	.map	= intc_irqpin_irq_domain_map,
 	.xlate  = irq_domain_xlate_twocell,
 };
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index cdf80b7794cd..df5bf21a701f 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -168,7 +168,7 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops irqc_irq_domain_ops = {
+static const struct irq_domain_ops irqc_irq_domain_ops = {
 	.map	= irqc_irq_domain_map,
 	.xlate  = irq_domain_xlate_twocell,
 };
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index c8d373fcd823..e96717f45ea1 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -502,7 +502,7 @@ err:
 	return -EINVAL;
 }
 
-static struct irq_domain_ops s3c24xx_irq_ops = {
+static const struct irq_domain_ops s3c24xx_irq_ops = {
 	.map = s3c24xx_irq_map,
 	.xlate = irq_domain_xlate_twocell,
 };
@@ -1228,7 +1228,7 @@ static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
 	return 0;
 }
 
-static struct irq_domain_ops s3c24xx_irq_ops_of = {
+static const struct irq_domain_ops s3c24xx_irq_ops_of = {
 	.map = s3c24xx_irq_map_of,
 	.xlate = s3c24xx_irq_xlate_of,
 };
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
index 64155b686081..83d6aa6464ee 100644
--- a/drivers/irqchip/irq-sun4i.c
+++ b/drivers/irqchip/irq-sun4i.c
@@ -89,7 +89,7 @@ static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops sun4i_irq_ops = {
+static const struct irq_domain_ops sun4i_irq_ops = {
 	.map = sun4i_irq_map,
 	.xlate = irq_domain_xlate_onecell,
 };
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 1ab451729a5c..888111b76ea0 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -132,7 +132,7 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-static struct irq_domain_ops fpga_irqdomain_ops = {
+static const struct irq_domain_ops fpga_irqdomain_ops = {
 	.map = fpga_irqdomain_map,
 	.xlate = irq_domain_xlate_onetwocell,
 };
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 54089debf2dc..d4ce331ea4a0 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -256,7 +256,7 @@ static void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
 	} while (handled);
 }
 
-static struct irq_domain_ops vic_irqdomain_ops = {
+static const struct irq_domain_ops vic_irqdomain_ops = {
 	.map = vic_irqdomain_map,
 	.xlate = irq_domain_xlate_onetwocell,
 };
diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c
index b7af816f2769..0b297009b856 100644
--- a/drivers/irqchip/irq-vt8500.c
+++ b/drivers/irqchip/irq-vt8500.c
@@ -173,7 +173,7 @@ static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
 	return 0;
 }
 
-static struct irq_domain_ops vt8500_irq_domain_ops = {
+static const struct irq_domain_ops vt8500_irq_domain_ops = {
 	.map = vt8500_irq_map,
 	.xlate = irq_domain_xlate_onecell,
 };
-- 
2.1.0



From pavel at ucw.cz  Mon Apr 27 13:36:08 2015
From: pavel at ucw.cz (Pavel Machek)
Date: Mon, 27 Apr 2015 22:36:08 +0200
Subject: [PATCH 01/13] thermal: Make temperatures consistently unsigned
 long
In-Reply-To: <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150427203608.GD29351@xo-6d-61-c0.localdomain>

On Thu 2015-03-26 16:53:48, Sascha Hauer wrote:
> The thermal framework uses int, long and unsigned long for temperatures
> in millicelsius. The majority of functions uses unsigned long, so change
> the remaining functions to use this type aswell.

Maybe millicelsius_t should be introduced, so that readers immediately know
what type it is? Some parts of kernel also use decicelsius and decikelvin, IIRC (ACPI).

									Pavel

>  	if (trip_type == THERMAL_TRIP_CRITICAL) {
>  		dev_emerg(&tz->device,
> -			  "critical temperature reached(%d C),shutting down\n",
> +			  "critical temperature reached(%lu C),shutting down\n",

space after , ?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From eddie.huang at mediatek.com  Tue Apr 28 00:35:53 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 15:35:53 +0800
Subject: [PATCH v3 0/3] Add Mediatek SoC RTC driver 
Message-ID: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>

RTC is one submodule of Mediatek MT6397 PMIC chip[1]. This series
support RTC driver that work with Mediatek SoC like MT8135, MT8173.
It implements second counter and also provide alarm function.

This series base on 4.1-rc1, Test ok on MT8173 platform.

[1] https://lkml.org/lkml/2015/1/23/325

Change in v3:
1. Replace magic number in mt6397-core.c
2. Add comment for some equation and write trigger.
3. Use regmap_bulk_read and regmap_bulk_write to avoid muliple regmap_read
   and regmap_write
4. Replace devm_request_threaded_irq with request_threaded_irq and add
   irq_dispose_mapping
5. Fix Tomasz Figa review comment.

Change in v2:
1. Move RTC address and interrupt to mt6397-core.c, and register
   these resource in mfd_cell.
   http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/323239.html
2. Remove dt-binding document due to register resouce in mfd_cell, not from
   device tree.
3. Update MAINTAINER file to add Mediatek RTC mainainter.
4. Add prefix mtk_ to some internal functions.
5. Fix racy condition
6. Check return value of regmap_read and regmap_write
7. Remove some unnecessary register readback, clear, then write.
8. Add disable alarm in mtk_rtc_set_alarm function
9. Fix Uwe Kleine-K?nig review comment

Eddie Huang (2):
  mfd: provide RTC resource in MT6397 MFD
  MAINTAINERS: add Mediatek RTC driver

Tianping Fang (1):
  rtc: mediatek: Add MT6397 RTC driver

 MAINTAINERS               |   7 +
 drivers/mfd/mt6397-core.c |  18 +++
 drivers/rtc/Kconfig       |  10 ++
 drivers/rtc/Makefile      |   1 +
 drivers/rtc/rtc-mt6397.c  | 388 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 424 insertions(+)
 create mode 100644 drivers/rtc/rtc-mt6397.c

--
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 00:35:54 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 15:35:54 +0800
Subject: [PATCH v3 1/3] mfd: provide RTC resource in MT6397 MFD
In-Reply-To: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
References: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430206556-18254-2-git-send-email-eddie.huang@mediatek.com>

Provide MT6397 RTC interrupt, base address, and register in
MT6397 MFD.

Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/mfd/mt6397-core.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 09bc780..08cfbd1 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -21,9 +21,27 @@
 #include <linux/mfd/mt6397/core.h>
 #include <linux/mfd/mt6397/registers.h>
 
+#define MT6397_RTC_BASE		0xe000
+#define MT6397_RTC_SIZE		0x3e
+
+static const struct resource mt6397_rtc_resources[] = {
+	{
+		.start = MT6397_RTC_BASE,
+		.end   = MT6397_RTC_BASE + MT6397_RTC_SIZE,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start = MT6397_IRQ_RTC,
+		.end   = MT6397_IRQ_RTC,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
 static const struct mfd_cell mt6397_devs[] = {
 	{
 		.name = "mt6397-rtc",
+		.num_resources = ARRAY_SIZE(mt6397_rtc_resources),
+		.resources = mt6397_rtc_resources,
 		.of_compatible = "mediatek,mt6397-rtc",
 	}, {
 		.name = "mt6397-regulator",
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 00:35:55 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 15:35:55 +0800
Subject: [PATCH v3 2/3] rtc: mediatek: Add MT6397 RTC driver
In-Reply-To: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
References: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430206556-18254-3-git-send-email-eddie.huang@mediatek.com>

From: Tianping Fang <tianping.fang at mediatek.com>

Add Mediatek MT6397 RTC driver

Signed-off-by: Tianping Fang <tianping.fang at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/rtc/Kconfig      |  10 ++
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-mt6397.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 399 insertions(+)
 create mode 100644 drivers/rtc/rtc-mt6397.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6149ae0..9608fcb 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1520,6 +1520,16 @@ config RTC_DRV_MOXART
 	   This driver can also be built as a module. If so, the module
 	   will be called rtc-moxart
 
+config RTC_DRV_MT6397
+	tristate "Mediatek Real Time Clock driver"
+	depends on MFD_MT6397 || COMPILE_TEST
+	help
+	  This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
+	  MT6397 PMIC. You should enable MT6397 PMIC MFD before select
+	  Mediatek(R) RTC driver.
+
+	  If you want to use Mediatek(R) RTC interface, select Y or M here.
+
 config RTC_DRV_XGENE
 	tristate "APM X-Gene RTC"
 	depends on HAS_IOMEM
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index c31731c..6ba0ce2 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -154,3 +154,4 @@ obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_XGENE)	+= rtc-xgene.o
 obj-$(CONFIG_RTC_DRV_SIRFSOC)	+= rtc-sirfsoc.o
 obj-$(CONFIG_RTC_DRV_MOXART)	+= rtc-moxart.o
+obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
new file mode 100644
index 0000000..0d96d02
--- /dev/null
+++ b/drivers/rtc/rtc-mt6397.c
@@ -0,0 +1,388 @@
+/*
+* Copyright (c) 2014-2015 MediaTek Inc.
+* Author: Tianping.Fang <tianping.fang at mediatek.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.
+*/
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/mfd/mt6397/core.h>
+
+#define RTC_BBPU		0x0000
+#define RTC_BBPU_CBUSY		BIT(6)
+
+#define RTC_WRTGR		0x003c
+
+#define RTC_IRQ_STA		0x0002
+#define RTC_IRQ_STA_AL		BIT(0)
+#define RTC_IRQ_STA_LP		BIT(3)
+
+#define RTC_IRQ_EN		0x0004
+#define RTC_IRQ_EN_AL		BIT(0)
+#define RTC_IRQ_EN_ONESHOT	BIT(2)
+#define RTC_IRQ_EN_LP		BIT(3)
+#define RTC_IRQ_EN_ONESHOT_AL	(RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
+
+#define RTC_AL_MASK		0x0008
+#define RTC_AL_MASK_DOW		BIT(4)
+
+#define RTC_TC_SEC		0x000a
+/* Min, Hour, Dom... register offset to RTC_TC_SEC */
+#define RTC_OFFSET_SEC		0
+#define RTC_OFFSET_MIN		1
+#define RTC_OFFSET_HOUR		2
+#define RTC_OFFSET_DOM		3
+#define RTC_OFFSET_DOW		4
+#define RTC_OFFSET_MTH		5
+#define RTC_OFFSET_YEAR		6
+#define RTC_OFFSET_COUNT	7
+
+#define RTC_AL_SEC		0x0018
+
+#define RTC_PDN2		0x002e
+#define RTC_PDN2_PWRON_ALARM	BIT(4)
+
+#define RTC_MIN_YEAR		1968
+#define RTC_BASE_YEAR		1900
+#define RTC_NUM_YEARS		128
+#define RTC_MIN_YEAR_OFFSET	(RTC_MIN_YEAR - RTC_BASE_YEAR)
+
+struct mt6397_rtc {
+	struct device		*dev;
+	struct rtc_device	*rtc_dev;
+	struct mutex		lock;
+	struct regmap		*regmap;
+	int			irq;
+	u32			addr_base;
+};
+
+static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
+{
+	unsigned long timeout = jiffies + HZ;
+	int ret;
+	u32 data;
+
+	ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1);
+	if (ret < 0)
+		return ret;
+
+	do {
+		cpu_relax();
+		ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU,
+				&data);
+		if (ret < 0)
+			goto exit;
+	} while ((data & RTC_BBPU_CBUSY) && time_after(timeout, jiffies));
+
+exit:
+	return ret;
+}
+
+static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data)
+{
+	struct mt6397_rtc *rtc = data;
+	u32 irqsta, irqen;
+	int ret;
+
+	ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_STA, &irqsta);
+	if ((ret >= 0) && (irqsta & RTC_IRQ_STA_AL)) {
+		rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+		irqen = irqsta & ~RTC_IRQ_EN_AL;
+		mutex_lock(&rtc->lock);
+		if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
+				 irqen) < 0)
+			mtk_rtc_write_trigger(rtc);
+		mutex_unlock(&rtc->lock);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int __mtk_rtc_read_time(struct mt6397_rtc *rtc,
+				struct rtc_time *tm, int *sec)
+{
+	int ret;
+	u16 data[RTC_OFFSET_COUNT];
+
+	mutex_lock(&rtc->lock);
+	ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+			data, RTC_OFFSET_COUNT);
+	if (ret < 0)
+		goto exit;
+
+	tm->tm_sec = data[RTC_OFFSET_SEC];
+	tm->tm_min = data[RTC_OFFSET_MIN];
+	tm->tm_hour = data[RTC_OFFSET_HOUR];
+	tm->tm_mday = data[RTC_OFFSET_DOM];
+	tm->tm_mon = data[RTC_OFFSET_MTH];
+	tm->tm_year = data[RTC_OFFSET_YEAR];
+
+	ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, sec);
+exit:
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	time64_t time;
+	struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+	int sec, ret;
+
+	do {
+		ret = __mtk_rtc_read_time(rtc, tm, &sec);
+		if (ret < 0)
+			goto exit;
+	} while (sec < tm->tm_sec);
+
+	/* HW register use 7 bits to store year data, minus
+	 * RTC_MIN_YEAR_OFFSET before write year data to register, and plus
+	 * RTC_MIN_YEAR_OFFSET back after read year from register
+	 */
+	tm->tm_year += RTC_MIN_YEAR_OFFSET;
+
+	/* HW register start mon from one, but tm_mon start from zero. */
+	tm->tm_mon--;
+	time = rtc_tm_to_time64(tm);
+
+	/* rtc_tm_to_time64 covert Gregorian date to seconds since
+	 * 01-01-1970 00:00:00, and this date is Thursday.
+	 */
+	tm->tm_wday = (time / 86400 + 4) % 7;
+
+exit:
+	return ret;
+}
+
+static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+	int ret;
+	u16 data[RTC_OFFSET_COUNT];
+
+	tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+	tm->tm_mon++;
+
+	data[RTC_OFFSET_SEC] = tm->tm_sec;
+	data[RTC_OFFSET_MIN] = tm->tm_min;
+	data[RTC_OFFSET_HOUR] = tm->tm_hour;
+	data[RTC_OFFSET_DOM] = tm->tm_mday;
+	data[RTC_OFFSET_MTH] = tm->tm_mon;
+	data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+	mutex_lock(&rtc->lock);
+	ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+			data, RTC_OFFSET_COUNT);
+	if (ret < 0)
+		goto exit;
+
+	/* Time register write to hardware after call trigger function */
+	ret = mtk_rtc_write_trigger(rtc);
+
+exit:
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct rtc_time *tm = &alm->time;
+	struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+	u32 irqen, pdn2;
+	int ret;
+	u16 data[RTC_OFFSET_COUNT];
+
+	mutex_lock(&rtc->lock);
+	ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, &irqen);
+	if (ret < 0)
+		goto err_exit;
+	ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_PDN2, &pdn2);
+	if (ret < 0)
+		goto err_exit;
+
+	ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+			data, RTC_OFFSET_COUNT);
+	if (ret < 0)
+		goto err_exit;
+
+	alm->enabled = !!(irqen & RTC_IRQ_EN_AL);
+	alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
+	mutex_unlock(&rtc->lock);
+
+	tm->tm_sec = data[RTC_OFFSET_SEC];
+	tm->tm_min = data[RTC_OFFSET_MIN];
+	tm->tm_hour = data[RTC_OFFSET_HOUR];
+	tm->tm_mday = data[RTC_OFFSET_DOM];
+	tm->tm_mon = data[RTC_OFFSET_MTH];
+	tm->tm_year = data[RTC_OFFSET_YEAR];
+
+	tm->tm_year += RTC_MIN_YEAR_OFFSET;
+	tm->tm_mon--;
+
+	return 0;
+err_exit:
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct rtc_time *tm = &alm->time;
+	struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+	int ret;
+	u16 data[RTC_OFFSET_COUNT];
+
+	tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+	tm->tm_mon++;
+
+	data[RTC_OFFSET_SEC] = tm->tm_sec;
+	data[RTC_OFFSET_MIN] = tm->tm_min;
+	data[RTC_OFFSET_HOUR] = tm->tm_hour;
+	data[RTC_OFFSET_DOM] = tm->tm_mday;
+	data[RTC_OFFSET_MTH] = tm->tm_mon;
+	data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+	mutex_lock(&rtc->lock);
+	if (alm->enabled) {
+		ret = regmap_bulk_write(rtc->regmap,
+				rtc->addr_base + RTC_AL_SEC,
+				data, RTC_OFFSET_COUNT);
+		if (ret < 0)
+			goto exit;
+		ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_AL_MASK,
+				RTC_AL_MASK_DOW);
+		if (ret < 0)
+			goto exit;
+		ret = regmap_update_bits(rtc->regmap,
+				rtc->addr_base + RTC_IRQ_EN,
+				RTC_IRQ_EN_ONESHOT_AL, RTC_IRQ_EN_ONESHOT_AL);
+		if (ret < 0)
+			goto exit;
+	} else {
+		ret = regmap_update_bits(rtc->regmap,
+					rtc->addr_base + RTC_IRQ_EN,
+					RTC_IRQ_EN_ONESHOT_AL, 0);
+		if (ret < 0)
+			goto exit;
+	}
+
+	/* All alarm time register write to hardware after calling
+	 * mtk_rtc_write_trigger. This can avoid race condition if alarm
+	 * occur happen during writing alarm time register.
+	 */
+	ret = mtk_rtc_write_trigger(rtc);
+exit:
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static struct rtc_class_ops mtk_rtc_ops = {
+	.read_time  = mtk_rtc_read_time,
+	.set_time   = mtk_rtc_set_time,
+	.read_alarm = mtk_rtc_read_alarm,
+	.set_alarm  = mtk_rtc_set_alarm,
+};
+
+static int mtk_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
+	struct mt6397_rtc *rtc;
+	int ret;
+
+	rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rtc->addr_base = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start);
+	if (rtc->irq <= 0)
+		return -EINVAL;
+
+	rtc->regmap = mt6397_chip->regmap;
+	rtc->dev = &pdev->dev;
+	mutex_init(&rtc->lock);
+
+	platform_set_drvdata(pdev, rtc);
+
+	ret = request_threaded_irq(rtc->irq, NULL,
+			mtk_rtc_irq_handler_thread,
+			IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+			"mt6397-rtc", rtc);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+			rtc->irq, ret);
+		goto out_dispose_irq;
+	}
+
+	rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev,
+				&mtk_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc_dev)) {
+		dev_err(&pdev->dev, "register rtc device failed\n");
+		ret = PTR_ERR(rtc->rtc_dev);
+		goto out_free_irq;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	return 0;
+
+out_free_irq:
+	free_irq(rtc->irq, rtc->rtc_dev);
+out_dispose_irq:
+	irq_dispose_mapping(rtc->irq);
+	return ret;
+}
+
+static int mtk_rtc_remove(struct platform_device *pdev)
+{
+	struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(rtc->rtc_dev);
+	free_irq(rtc->irq, rtc->rtc_dev);
+	irq_dispose_mapping(rtc->irq);
+
+	return 0;
+}
+
+static const struct of_device_id mt6397_rtc_of_match[] = {
+	{ .compatible = "mediatek,mt6397-rtc", },
+	{ }
+};
+
+static struct platform_driver mtk_rtc_driver = {
+	.driver = {
+		.name = "mt6397-rtc",
+		.of_match_table = mt6397_rtc_of_match,
+	},
+	.probe	= mtk_rtc_probe,
+	.remove = mtk_rtc_remove,
+};
+
+module_platform_driver(mtk_rtc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Tianping Fang <tianping.fang at mediatek.com>");
+MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
+MODULE_ALIAS("platform:mt6397-rtc");
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 00:35:56 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 15:35:56 +0800
Subject: [PATCH v3 3/3] MAINTAINERS: add Mediatek RTC driver
In-Reply-To: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
References: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430206556-18254-4-git-send-email-eddie.huang@mediatek.com>

Add Mediatek RTC driver to maintainer entry.

Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2e5bbc0..eb80610 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1223,6 +1223,13 @@ W:	http://www.digriz.org.uk/ts78xx/kernel
 S:	Maintained
 F:	arch/arm/mach-orion5x/ts78xx-*
 
+ARM/Mediatek RTC DRIVER
+M:	Eddie Huang <eddie.huang at mediatek.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/rtc/rtc-mt*
+
 ARM/Mediatek SoC support
 M:	Matthias Brugger <matthias.bgg at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
1.8.1.1.dirty



From yong.wu at mediatek.com  Tue Apr 28 00:41:21 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Tue, 28 Apr 2015 15:41:21 +0800
Subject: [RFC PATCH] iommu: add ARM short descriptor page table allocator.
Message-ID: <1430206881-18294-1-git-send-email-yong.wu@mediatek.com>

This patch is for ARM Short Descriptor Format.It has 2-levels
pagetable and the allocator supports 4K/64K/1M/16M.

Signed-off-by: Yong Wu <yong.wu at mediatek.com>
---
 drivers/iommu/Kconfig                |   7 +
 drivers/iommu/Makefile               |   1 +
 drivers/iommu/io-pgtable-arm-short.c | 489 +++++++++++++++++++++++++++++++++++
 drivers/iommu/io-pgtable.c           |   4 +
 drivers/iommu/io-pgtable.h           |   6 +
 5 files changed, 507 insertions(+)
 create mode 100644 drivers/iommu/io-pgtable-arm-short.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index baa0d97..8e50e73 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -38,6 +38,13 @@ config IOMMU_IO_PGTABLE_LPAE_SELFTEST
 
 	  If unsure, say N here.
 
+config IOMMU_IO_PGTABLE_SHORT
+	bool "ARMv7/v8 Short Descriptor Format"
+	select IOMMU_IO_PGTABLE
+	help
+	  Enable support for the ARM Short descriptor pagetable format.
+	  It has 2-levels pagetable and The allocator supports 4K/64K/1M/16M.
+
 endmenu
 
 config IOMMU_IOVA
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 080ffab..815b3c8 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_IOMMU_API) += iommu-traces.o
 obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
+obj-$(CONFIG_IOMMU_IO_PGTABLE_SHORT) += io-pgtable-arm-short.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
diff --git a/drivers/iommu/io-pgtable-arm-short.c b/drivers/iommu/io-pgtable-arm-short.c
new file mode 100644
index 0000000..8d723ec
--- /dev/null
+++ b/drivers/iommu/io-pgtable-arm-short.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2014-2015 MediaTek Inc.
+ * Author: Yong Wu <yong.wu at mediatek.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.
+ */
+#define pr_fmt(fmt)	"arm-short-desc io-pgtable: "fmt
+
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/iommu.h>
+#include <linux/errno.h>
+
+#include "io-pgtable.h"
+
+typedef u32 arm_short_iopte;
+
+struct arm_short_io_pgtable {
+	struct io_pgtable	iop;
+	struct kmem_cache	*ptekmem;
+	size_t			pgd_size;
+	void			*pgd;
+};
+
+#define io_pgtable_short_to_data(x)				\
+	container_of((x), struct arm_short_io_pgtable, iop)
+
+#define io_pgtable_ops_to_pgtable(x)				\
+	container_of((x), struct io_pgtable, ops)
+
+#define io_pgtable_short_ops_to_data(x)				\
+	io_pgtable_short_to_data(io_pgtable_ops_to_pgtable(x))
+
+#define ARM_SHORT_MAX_ADDR_BITS			32
+
+#define ARM_SHORT_PGDIR_SHIFT			20
+#define ARM_SHORT_PAGE_SHIFT			12
+#define ARM_SHORT_PTRS_PER_PTE			256
+#define ARM_SHORT_BYTES_PER_PTE			1024
+
+/* 1 level pagetable */
+#define ARM_SHORT_F_PGD_TYPE_PAGE		(0x1)
+#define ARM_SHORT_F_PGD_TYPE_PAGE_MSK		(0x3)
+#define ARM_SHORT_F_PGD_TYPE_SECTION		(0x2)
+#define ARM_SHORT_F_PGD_TYPE_SUPERSECTION	(0x2 | (1 << 18))
+#define ARM_SHORT_F_PGD_TYPE_SECTION_MSK	(0x3 | (1 << 18))
+#define ARM_SHORT_F_PGD_TYPE_IS_PAGE(pgd)	(((pgd) & 0x3) == 1)
+#define ARM_SHORT_F_PGD_TYPE_IS_SECTION(pgd)		\
+	(((pgd) & ARM_SHORT_F_PGD_TYPE_SECTION_MSK)	\
+		== ARM_SHORT_F_PGD_TYPE_SECTION)
+#define ARM_SHORT_F_PGD_TYPE_IS_SUPERSECTION(pgd)	\
+	(((pgd) & ARM_SHORT_F_PGD_TYPE_SECTION_MSK)	\
+		== ARM_SHORT_F_PGD_TYPE_SUPERSECTION)
+
+#define ARM_SHORT_F_PGD_B_BIT			BIT(2)
+#define ARM_SHORT_F_PGD_C_BIT			BIT(3)
+#define ARM_SHORT_F_PGD_IMPLE_BIT		BIT(9)
+#define ARM_SHORT_F_PGD_S_BIT			BIT(16)
+#define ARM_SHORT_F_PGD_NG_BIT			BIT(17)
+#define ARM_SHORT_F_PGD_NS_BIT_PAGE		BIT(3)
+#define ARM_SHORT_F_PGD_NS_BIT_SECTION		BIT(19)
+
+#define ARM_SHORT_F_PGD_PA_PAGETABLE_MSK	0xfffffc00
+#define ARM_SHORT_F_PGD_PA_SECTION_MSK		0xfff00000
+#define ARM_SHORT_F_PGD_PA_SUPERSECTION_MSK	0xff000000
+
+/* 2 level pagetable */
+#define ARM_SHORT_F_PTE_TYPE_GET(val)		((val) & 0x3)
+#define ARM_SHORT_F_PTE_TYPE_LARGE		BIT(0)
+#define ARM_SHORT_F_PTE_TYPE_SMALL		BIT(1)
+#define ARM_SHORT_F_PTE_B_BIT			BIT(2)
+#define ARM_SHORT_F_PTE_C_BIT			BIT(3)
+#define ARM_SHORT_F_PTE_IMPLE_BIT		BIT(9)
+#define ARM_SHORT_F_PTE_S_BIT			BIT(10)
+#define ARM_SHORT_F_PTE_PA_LARGE_MSK            0xffff0000
+#define ARM_SHORT_F_PTE_PA_SMALL_MSK            0xfffff000
+
+#define ARM_SHORT_PGD_IDX(a)			((a) >> ARM_SHORT_PGDIR_SHIFT)
+#define ARM_SHORT_PTE_IDX(a)			\
+	(((a) >> ARM_SHORT_PAGE_SHIFT) & 0xff)
+#define ARM_SHORT_GET_PTE_VA(pgd)		\
+	(phys_to_virt((unsigned long)pgd & ARM_SHORT_F_PGD_PA_PAGETABLE_MSK))
+
+static arm_short_iopte *
+arm_short_get_pte_in_pgd(arm_short_iopte curpgd, unsigned int iova)
+{
+	arm_short_iopte *pte;
+
+	pte = ARM_SHORT_GET_PTE_VA(curpgd);
+	pte += ARM_SHORT_PTE_IDX(iova);
+	return pte;
+}
+
+static arm_short_iopte *
+arm_short_supersection_start(arm_short_iopte *pgd)
+{
+	return (arm_short_iopte *)(round_down((unsigned long)pgd, (16 * 4)));
+}
+
+static int _arm_short_check_free_pte(struct arm_short_io_pgtable *data,
+				     arm_short_iopte *pgd)
+{
+	arm_short_iopte *pte;
+	int i;
+
+	pte = ARM_SHORT_GET_PTE_VA(*pgd);
+
+	for (i = 0; i < ARM_SHORT_PTRS_PER_PTE; i++) {
+		if (pte[i] != 0)
+			return 1;
+	}
+
+	/* Free PTE */
+	kmem_cache_free(data->ptekmem, pte);
+	*pgd = 0;
+
+	return 0;
+}
+
+static phys_addr_t arm_short_iova_to_phys(struct io_pgtable_ops *ops,
+					  unsigned long iova)
+{
+	struct arm_short_io_pgtable *data = io_pgtable_short_ops_to_data(ops);
+	arm_short_iopte *pte, *pgd = data->pgd;
+	phys_addr_t pa = 0;
+
+	pgd += ARM_SHORT_PGD_IDX(iova);
+
+	if (ARM_SHORT_F_PGD_TYPE_IS_PAGE(*pgd)) {
+		pte = arm_short_get_pte_in_pgd(*pgd, iova);
+
+		if (ARM_SHORT_F_PTE_TYPE_GET(*pte)
+		    == ARM_SHORT_F_PTE_TYPE_LARGE) {
+			pa = (*pte) & ARM_SHORT_F_PTE_PA_LARGE_MSK;
+			pa |= iova & (~ARM_SHORT_F_PTE_PA_LARGE_MSK);
+		} else if (ARM_SHORT_F_PTE_TYPE_GET(*pte)
+			   == ARM_SHORT_F_PTE_TYPE_SMALL) {
+			pa = (*pte) & ARM_SHORT_F_PTE_PA_SMALL_MSK;
+			pa |= iova & (~ARM_SHORT_F_PTE_PA_SMALL_MSK);
+		}
+	} else {
+		if (ARM_SHORT_F_PGD_TYPE_IS_SECTION(*pgd)) {
+			pa = (*pgd) & ARM_SHORT_F_PGD_PA_SECTION_MSK;
+			pa |= iova & (~ARM_SHORT_F_PGD_PA_SECTION_MSK);
+		} else if (ARM_SHORT_F_PGD_TYPE_IS_SUPERSECTION(*pgd)) {
+			pa = (*pgd) & ARM_SHORT_F_PGD_PA_SUPERSECTION_MSK;
+			pa |= iova & (~ARM_SHORT_F_PGD_PA_SUPERSECTION_MSK);
+		}
+	}
+
+	return pa;
+}
+
+static int arm_short_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+			   size_t size)
+{
+	struct arm_short_io_pgtable *data = io_pgtable_short_ops_to_data(ops);
+	arm_short_iopte *pgd;
+	unsigned long iova_start = iova;
+	unsigned long end_plus_1 = (unsigned long)iova + size;
+	const struct iommu_gather_ops *tlb = data->iop.cfg.tlb;
+	void *cookie = data->iop.cookie;
+	int ret;
+
+	do {
+		pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(iova);
+
+		if (ARM_SHORT_F_PGD_TYPE_IS_PAGE(*pgd)) {
+			arm_short_iopte *pte;
+			unsigned int pte_offset;
+			unsigned int num_to_clean;
+
+			pte_offset = ARM_SHORT_PTE_IDX(iova);
+			num_to_clean =
+			    min((unsigned int)((end_plus_1 - iova) / PAGE_SIZE),
+				(ARM_SHORT_PTRS_PER_PTE - pte_offset));
+
+			pte = arm_short_get_pte_in_pgd(*pgd, iova);
+
+			memset(pte, 0, num_to_clean * sizeof(arm_short_iopte));
+
+			ret = _arm_short_check_free_pte(data, pgd);
+			if (ret == 1)/* pte is not freed, need to flush pte */
+				tlb->flush_pgtable(
+					pte,
+					num_to_clean * sizeof(arm_short_iopte),
+					cookie);
+			else
+				tlb->flush_pgtable(pgd, sizeof(arm_short_iopte),
+						   cookie);
+
+			iova += num_to_clean << PAGE_SHIFT;
+		} else if (ARM_SHORT_F_PGD_TYPE_IS_SECTION(*pgd)) {
+			*pgd = 0;
+
+			tlb->flush_pgtable(pgd, sizeof(arm_short_iopte),
+					   cookie);
+			iova += SZ_1M;
+		} else if (ARM_SHORT_F_PGD_TYPE_IS_SUPERSECTION(*pgd)) {
+			arm_short_iopte *start;
+
+			start = arm_short_supersection_start(pgd);
+			if (unlikely(start != pgd))
+				pr_warn("%s:suppersection start isn't aligned.iova=0x%lx,pgd=0x%x\n",
+					__func__, iova, *pgd);
+
+			memset(start, 0, 16 * sizeof(arm_short_iopte));
+
+			tlb->flush_pgtable(start, 16 * sizeof(arm_short_iopte),
+					   cookie);
+
+			iova = (iova + SZ_16M) & (~(SZ_16M - 1));
+		} else {
+			break;
+		}
+	} while (iova < end_plus_1 && iova);
+
+	tlb->tlb_add_flush(iova_start, size, true, cookie);
+
+	return 0;
+}
+
+static arm_short_iopte __arm_short_pte_port(unsigned int prot, bool large)
+{
+	arm_short_iopte pteprot;
+
+	pteprot = ARM_SHORT_F_PTE_S_BIT;
+
+	pteprot |= large ? ARM_SHORT_F_PTE_TYPE_LARGE :
+				ARM_SHORT_F_PTE_TYPE_SMALL;
+
+	if (prot & IOMMU_CACHE)
+		pteprot |=  ARM_SHORT_F_PTE_B_BIT | ARM_SHORT_F_PTE_C_BIT;
+
+	return pteprot;
+}
+
+static arm_short_iopte __arm_short_pgd_port(int prot, bool super)
+{
+	arm_short_iopte pgdprot;
+
+	pgdprot = ARM_SHORT_F_PGD_S_BIT;
+	pgdprot |= super ? ARM_SHORT_F_PGD_TYPE_SUPERSECTION :
+				ARM_SHORT_F_PGD_TYPE_SECTION;
+	if (prot & IOMMU_CACHE)
+		pgdprot |= ARM_SHORT_F_PGD_C_BIT | ARM_SHORT_F_PGD_B_BIT;
+
+	return pgdprot;
+}
+
+static int _arm_short_map_page(struct arm_short_io_pgtable *data,
+			       unsigned int iova, phys_addr_t pa,
+			       unsigned int prot, bool largepage)
+{
+	arm_short_iopte *pgd = data->pgd;
+	arm_short_iopte *pte;
+	arm_short_iopte pgdprot, pteprot;
+	arm_short_iopte mask = largepage ? ARM_SHORT_F_PTE_PA_LARGE_MSK :
+						ARM_SHORT_F_PTE_PA_SMALL_MSK;
+	int i, ptenum = largepage ? 16 : 1;
+	bool ptenew = false;
+	void *pte_new_va;
+	void *cookie = data->iop.cookie;
+
+	if ((iova | pa) & (~mask)) {
+		pr_err("IOVA|PA Not Aligned(iova=0x%x pa=0x%pa type=%s)\n",
+		       iova, &pa, largepage ? "large page" : "small page");
+		return -EINVAL;
+	}
+
+	pgdprot = ARM_SHORT_F_PGD_TYPE_PAGE;
+	if (data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_NS)
+		pgdprot |= ARM_SHORT_F_PGD_NS_BIT_PAGE;
+
+	pgd += ARM_SHORT_PGD_IDX(iova);
+
+	if (!(*pgd)) {
+		pte_new_va = kmem_cache_zalloc(data->ptekmem, GFP_KERNEL);
+		if (unlikely(!pte_new_va)) {
+			pr_err("Failed to alloc pte\n");
+			return -ENOMEM;
+		}
+
+		/* Check pte alignment -- must 1K align */
+		if (unlikely((unsigned long)pte_new_va &
+			     (ARM_SHORT_BYTES_PER_PTE - 1))) {
+			pr_err("The new pte is not aligned! (va=0x%p)\n",
+			       pte_new_va);
+			kmem_cache_free(data->ptekmem, (void *)pte_new_va);
+			return -ENOMEM;
+		}
+		ptenew = true;
+		*pgd = virt_to_phys(pte_new_va) | pgdprot;
+		kmemleak_ignore(pte_new_va);
+		data->iop.cfg.tlb->flush_pgtable(pgd, sizeof(arm_short_iopte),
+						 cookie);
+	} else {
+		/* Someone else may have allocated for this pgd */
+		if (((*pgd) & (~ARM_SHORT_F_PGD_PA_PAGETABLE_MSK)) != pgdprot) {
+			pr_err("The prot of old pgd is not Right!iova=0x%x pgd=0x%x pgprot=0x%x\n",
+			       iova, (*pgd), pgdprot);
+			return -EEXIST;
+		}
+	}
+
+	pteprot = (arm_short_iopte)pa;
+	pteprot |= __arm_short_pte_port(prot, largepage);
+
+	pte = arm_short_get_pte_in_pgd(*pgd, iova);
+
+	pr_debug("iova:0x%x,pte:0x%p(0x%x),prot:0x%x-%s\n",
+		 iova, pte, ARM_SHORT_PTE_IDX(iova), pteprot,
+		 largepage ? "large page" : "small page");
+
+	for (i = 0; i < ptenum; i++) {
+		if (pte[i]) {
+			pr_err("The To-Map pte exists!(iova=0x%x pte=0x%x i=%d)\n",
+			       iova, pte[i], i);
+			goto err_out;
+		}
+		pte[i] = pteprot;
+	}
+
+	data->iop.cfg.tlb->flush_pgtable(pte, ptenum * sizeof(arm_short_iopte),
+					 cookie);
+	return 0;
+
+ err_out:
+	for (i--; i >= 0; i--)
+		pte[i] = 0;
+	if (ptenew)
+		kmem_cache_free(data->ptekmem, pte_new_va);
+	return -EEXIST;
+}
+
+static int _arm_short_map_section(struct arm_short_io_pgtable *data,
+				  unsigned int iova, phys_addr_t pa,
+				  int prot, bool supersection)
+{
+	arm_short_iopte pgprot;
+	arm_short_iopte mask = supersection ?
+				ARM_SHORT_F_PGD_PA_SUPERSECTION_MSK :
+				ARM_SHORT_F_PGD_PA_SECTION_MSK;
+	arm_short_iopte *pgd = data->pgd;
+	int i;
+	unsigned int pgdnum = supersection ? 16 : 1;
+
+	if ((iova | pa) & (~mask)) {
+		pr_err("IOVA|PA Not Aligned(iova=0x%x pa=0x%pa type=%s)\n",
+		       iova, &pa, supersection ? "supersection" : "section");
+		return -EINVAL;
+	}
+
+	pgprot = (arm_short_iopte)pa;
+
+	if (data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_NS)
+		pgprot |= ARM_SHORT_F_PGD_NS_BIT_SECTION;
+
+	pgprot |= __arm_short_pgd_port(prot, supersection);
+
+	pgd += ARM_SHORT_PGD_IDX(iova);
+
+	pr_debug("iova:0x%x,pgd:0x%p(0x%p+0x%x),value:0x%x-%s\n",
+		 iova, pgd, data->pgd, ARM_SHORT_PGD_IDX(iova),
+		 pgprot, supersection ? "supersection" : "section");
+
+	for (i = 0; i < pgdnum; i++) {
+		if (unlikely(*pgd)) {
+			pr_err("The To-Map pdg exists!(iova=0x%x pgd=0x%x i=%d)\n",
+			       iova, pgd[i], i);
+			goto err_out;
+		}
+		pgd[i] = pgprot;
+	}
+	data->iop.cfg.tlb->flush_pgtable(pgd,
+					 pgdnum * sizeof(arm_short_iopte),
+					 data->iop.cookie);
+	return 0;
+
+ err_out:
+	for (i--; i >= 0; i--)
+		pgd[i] = 0;
+	return -EEXIST;
+}
+
+static int arm_short_map(struct io_pgtable_ops *ops, unsigned long iova,
+			 phys_addr_t paddr, size_t size, int prot)
+{
+	struct arm_short_io_pgtable *data = io_pgtable_short_ops_to_data(ops);
+	const struct iommu_gather_ops *tlb = data->iop.cfg.tlb;
+	int ret;
+
+	if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
+		return -EINVAL;
+
+	if (size == SZ_4K) {/* most case */
+		ret = _arm_short_map_page(data, iova, paddr, prot, false);
+	} else if (size == SZ_64K) {
+		ret = _arm_short_map_page(data, iova, paddr, prot, true);
+	} else if (size == SZ_1M) {
+		ret = _arm_short_map_section(data, iova, paddr, prot, false);
+	} else if (size == SZ_16M) {
+		ret = _arm_short_map_section(data, iova, paddr, prot, true);
+	} else {
+		ret = -EINVAL;
+	}
+	tlb->tlb_add_flush(iova, size, true, data->iop.cookie);
+	return ret;
+}
+
+static struct io_pgtable *
+arm_short_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
+{
+	struct arm_short_io_pgtable *data;
+
+	if (cfg->ias != 32)
+		return NULL;
+
+	if (cfg->oas > ARM_SHORT_MAX_ADDR_BITS)
+		return NULL;
+
+	cfg->pgsize_bitmap &= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return NULL;
+
+	data->pgd_size = SZ_16K;
+
+	data->pgd = alloc_pages_exact(data->pgd_size, GFP_KERNEL | __GFP_ZERO);
+	if (!data->pgd)
+		goto out_free_data;
+
+	cfg->tlb->flush_pgtable(data->pgd, data->pgd_size, cookie);
+
+	/* kmem for pte */
+	data->ptekmem = kmem_cache_create("short-descriptor-pte",
+					   ARM_SHORT_BYTES_PER_PTE,
+					   ARM_SHORT_BYTES_PER_PTE,
+					   0, NULL);
+
+	if (IS_ERR_OR_NULL(data->ptekmem)) {
+		pr_err("Failed to Create cached mem for PTE %ld\n",
+		       PTR_ERR(data->ptekmem));
+		goto out_free_pte;
+	}
+
+	/* TTBRs */
+	cfg->arm_short_cfg.ttbr[0] = virt_to_phys(data->pgd);
+	cfg->arm_short_cfg.ttbr[1] = 0;
+
+	cfg->arm_short_cfg.tcr = 0;
+
+	data->iop.ops = (struct io_pgtable_ops) {
+		.map		= arm_short_map,
+		.unmap		= arm_short_unmap,
+		.iova_to_phys	= arm_short_iova_to_phys,
+	};
+
+	return &data->iop;
+
+out_free_pte:
+	free_pages_exact(data->pgd, data->pgd_size);
+out_free_data:
+	kfree(data);
+	return NULL;
+}
+
+static void arm_short_free_pgtable(struct io_pgtable *iop)
+{
+	struct arm_short_io_pgtable *data = io_pgtable_short_to_data(iop);
+
+	kmem_cache_destroy(data->ptekmem);
+	free_pages_exact(data->pgd, data->pgd_size);
+	kfree(data);
+}
+
+struct io_pgtable_init_fns io_pgtable_arm_short_init_fns = {
+	.alloc	= arm_short_alloc_pgtable,
+	.free	= arm_short_free_pgtable,
+};
+
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index 6436fe2..14a9b3a 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -28,6 +28,7 @@ extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
 extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns;
 extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns;
 extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_arm_short_init_fns;
 
 static const struct io_pgtable_init_fns *
 io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] =
@@ -38,6 +39,9 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] =
 	[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
 	[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
 #endif
+#ifdef CONFIG_IOMMU_IO_PGTABLE_SHORT
+	[ARM_SHORT_DESC] = &io_pgtable_arm_short_init_fns,
+#endif
 };
 
 struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
index 10e32f6..47efaab 100644
--- a/drivers/iommu/io-pgtable.h
+++ b/drivers/iommu/io-pgtable.h
@@ -9,6 +9,7 @@ enum io_pgtable_fmt {
 	ARM_32_LPAE_S2,
 	ARM_64_LPAE_S1,
 	ARM_64_LPAE_S2,
+	ARM_SHORT_DESC,
 	IO_PGTABLE_NUM_FMTS,
 };
 
@@ -62,6 +63,11 @@ struct io_pgtable_cfg {
 			u64	vttbr;
 			u64	vtcr;
 		} arm_lpae_s2_cfg;
+
+		struct {
+			u64	ttbr[2];
+			u64	tcr;
+		} arm_short_cfg;
 	};
 };
 
-- 
1.8.1.1.dirty



From s.hauer at pengutronix.de  Tue Apr 28 00:42:24 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 09:42:24 +0200
Subject: [PATCH 01/13] thermal: Make temperatures consistently unsigned
 long
In-Reply-To: <20150427203608.GD29351@xo-6d-61-c0.localdomain>
References: <1427385240-6086-1-git-send-email-s.hauer@pengutronix.de>
 <1427385240-6086-2-git-send-email-s.hauer@pengutronix.de>
 <20150427203608.GD29351@xo-6d-61-c0.localdomain>
Message-ID: <20150428074224.GI6325@pengutronix.de>

On Mon, Apr 27, 2015 at 10:36:08PM +0200, Pavel Machek wrote:
> On Thu 2015-03-26 16:53:48, Sascha Hauer wrote:
> > The thermal framework uses int, long and unsigned long for temperatures
> > in millicelsius. The majority of functions uses unsigned long, so change
> > the remaining functions to use this type aswell.
> 
> Maybe millicelsius_t should be introduced, so that readers immediately know
> what type it is? Some parts of kernel also use decicelsius and decikelvin, IIRC (ACPI).

I have no strong opinion on this. I'll send out the next version without
typedef for now. Since in my patch I identified most places which need a
type change anyway it might be a good opportunity to change to a typedef
if we want to. Any other opinions on this?

> 
> 									Pavel
> 
> >  	if (trip_type == THERMAL_TRIP_CRITICAL) {
> >  		dev_emerg(&tz->device,
> > -			  "critical temperature reached(%d C),shutting down\n",
> > +			  "critical temperature reached(%lu C),shutting down\n",
> 
> space after , ?

Turns out that in the new version of this series I don't have to modify
this line anymore. Made this a separate patch.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From u.kleine-koenig at pengutronix.de  Tue Apr 28 00:45:54 2015
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Tue, 28 Apr 2015 09:45:54 +0200
Subject: [PATCH v3 1/3] mfd: provide RTC resource in MT6397 MFD
In-Reply-To: <1430206556-18254-2-git-send-email-eddie.huang@mediatek.com>
References: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
 <1430206556-18254-2-git-send-email-eddie.huang@mediatek.com>
Message-ID: <20150428074554.GZ19431@pengutronix.de>

Hello,

On Tue, Apr 28, 2015 at 03:35:54PM +0800, Eddie Huang wrote:
> Provide MT6397 RTC interrupt, base address, and register in
> MT6397 MFD.
> 
> Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
> ---
>  drivers/mfd/mt6397-core.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> index 09bc780..08cfbd1 100644
> --- a/drivers/mfd/mt6397-core.c
> +++ b/drivers/mfd/mt6397-core.c
> @@ -21,9 +21,27 @@
>  #include <linux/mfd/mt6397/core.h>
>  #include <linux/mfd/mt6397/registers.h>
>  
> +#define MT6397_RTC_BASE		0xe000
> +#define MT6397_RTC_SIZE		0x3e
> +
> +static const struct resource mt6397_rtc_resources[] = {
> +	{
> +		.start = MT6397_RTC_BASE,
> +		.end   = MT6397_RTC_BASE + MT6397_RTC_SIZE,
> +		.flags  = IORESOURCE_MEM,
It's definitly a matter of taste if you align the rhs here, but if you
do, do it consitently. That is, either make sure that all equal signs
are in a single column (at least per struct resource), or use a single
space between variable name and =.

If you want to hear my personal preference: I always use a single space.
As if you have to add
	.somelongvariablename = somevalue

you have to touch all other lines, too, which is ugly.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From s.hauer at pengutronix.de  Tue Apr 28 01:25:50 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:50 +0200
Subject: [PATCH v2] Thermal cleanups and hardware trip points
Message-ID: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>

This series adds support for hardware trip points. It picks up earlier
work from Mikko Perttunen. Mikko implemented hardware trip points as part
of the device tree support. It was suggested back then to move the
functionality to the thermal core instead of putting more code into the
device tree support. This series does exactly that.

The majority of the patches are cleanups and fixes. Only the last two
patches actually implement the hardware trip points.

Note that the hardware trip points are not very well tested currently
and I still have no ready-to-post driver using them. However, Brian
Norris showed interest in these patches, so I am including the patches
in this series nevertheless.

All comments welcome

Changes since v1:
- Use int instead of unsigned long consistently for temperatures
- Instead of misfixing the emulation code add a comment how the
  code is meant
- Add doc entry for .set_trips callback
- initialize prev_low_trip/prev_high_trip properly
- get tz->lock before calling thermal_zone_set_trips()



From s.hauer at pengutronix.de  Tue Apr 28 01:25:59 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:59 +0200
Subject: [PATCH 09/13] thermal: Allow sensor ops to fail with -ENOSYS
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-10-git-send-email-s.hauer@pengutronix.de>

The thermal core uses the existence of the .get_temp, .get_trend and
.set_emul_temp to detect whether this operation exists and should be
used or whether it should be emulated in software. This makes problems
for of-thermal which has to modify the struct thermal_zone_device_ops
during runtime whenever a sensor is registered or unregistered.

Let the core test for -ENOSYS from these callbacks and treat it like
if the callbacks were not present.

This allows of-thermal to always set the sensor related callbacks and
to make struct thermal_zone_device_ops const again.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 81ebc24..0f3d26c 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -413,13 +413,16 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
  */
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	int ret = -EINVAL;
+	int ret;
 	int count;
 	int crit_temp = INT_MAX;
 	enum thermal_trip_type type;
 
-	if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
-		goto exit;
+	if (!tz || IS_ERR(tz))
+		return -EINVAL;
+
+	if (!tz->ops->get_temp)
+		return -ENOSYS;
 
 	mutex_lock(&tz->lock);
 
@@ -445,7 +448,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 	}
 
 	mutex_unlock(&tz->lock);
-exit:
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
@@ -454,10 +457,11 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 {
 	int temp, ret, count;
 
-	if (!tz->ops->get_temp)
+	ret = thermal_zone_get_temp(tz, &temp);
+
+	if (ret == -ENOSYS)
 		return;
 
-	ret = thermal_zone_get_temp(tz, &temp);
 	if (ret) {
 		if (ret != -EAGAIN)
 			dev_warn(&tz->device,
@@ -783,10 +787,16 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
 	if (kstrtoul(buf, 10, &temperature))
 		return -EINVAL;
 
-	if (!tz->ops->set_emul_temp) {
+	if (tz->ops->set_emul_temp)
+		ret = tz->ops->set_emul_temp(tz, temperature);
+	else
+		ret = -ENOSYS;
+
+	if (ret == -ENOSYS) {
 		mutex_lock(&tz->lock);
 		tz->emul_temperature = temperature;
 		mutex_unlock(&tz->lock);
+		ret = 0;
 	} else {
 		ret = tz->ops->set_emul_temp(tz, temperature);
 	}
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:26:01 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:26:01 +0200
Subject: [PATCH 11/13] thermal: Make struct thermal_zone_device_ops const
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-12-git-send-email-s.hauer@pengutronix.de>

Now that the of thermal support no longer changes the
thermal_zone_device_ops it can be const again.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 Documentation/thermal/sysfs-api.txt                    | 2 +-
 drivers/acpi/thermal.c                                 | 2 +-
 drivers/platform/x86/acerhdf.c                         | 2 +-
 drivers/platform/x86/intel_mid_thermal.c               | 2 +-
 drivers/power/power_supply_core.c                      | 2 +-
 drivers/thermal/armada_thermal.c                       | 2 +-
 drivers/thermal/db8500_thermal.c                       | 2 +-
 drivers/thermal/dove_thermal.c                         | 2 +-
 drivers/thermal/imx_thermal.c                          | 2 +-
 drivers/thermal/int340x_thermal/int3400_thermal.c      | 2 +-
 drivers/thermal/int340x_thermal/int340x_thermal_zone.c | 2 +-
 drivers/thermal/intel_soc_dts_thermal.c                | 2 +-
 drivers/thermal/kirkwood_thermal.c                     | 2 +-
 drivers/thermal/of-thermal.c                           | 2 +-
 drivers/thermal/rcar_thermal.c                         | 2 +-
 drivers/thermal/spear_thermal.c                        | 2 +-
 drivers/thermal/st/st_thermal.c                        | 2 +-
 drivers/thermal/thermal_core.c                         | 2 +-
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c     | 2 +-
 drivers/thermal/x86_pkg_temp_thermal.c                 | 2 +-
 include/linux/thermal.h                                | 6 +++---
 21 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 87519cb..bb346a2 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -33,7 +33,7 @@ temperature) and throttle appropriate devices.
 1.1 thermal zone device interface
 1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *type,
 		int trips, int mask, void *devdata,
-		struct thermal_zone_device_ops *ops,
+		const struct thermal_zone_device_ops *ops,
 		const struct thermal_zone_params *tzp,
 		int passive_delay, int polling_delay))
 
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 68bff60..6b11462 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -869,7 +869,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
 	return acpi_thermal_cooling_device_cb(thermal, cdev, false);
 }
 
-static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
 	.bind = acpi_thermal_bind_cooling_device,
 	.unbind	= acpi_thermal_unbind_cooling_device,
 	.get_temp = thermal_get_temp,
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index f2ce63c..bae9ca0 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -482,7 +482,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
 }
 
 /* bind callback functions to thermalzone */
-static struct thermal_zone_device_ops acerhdf_dev_ops = {
+static const struct thermal_zone_device_ops acerhdf_dev_ops = {
 	.bind = acerhdf_bind,
 	.unbind = acerhdf_unbind,
 	.get_temp = acerhdf_get_ec_temp,
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 0944e83..069d36b 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -460,7 +460,7 @@ static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
 }
 
 /* Can't be const */
-static struct thermal_zone_device_ops tzd_ops = {
+static const struct thermal_zone_device_ops tzd_ops = {
 	.get_temp = read_curr_temp,
 };
 
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 87e2fd1..878cb4e 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -509,7 +509,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
 	return ret;
 }
 
-static struct thermal_zone_device_ops psy_tzd_ops = {
+static const struct thermal_zone_device_ops psy_tzd_ops = {
 	.get_temp = power_supply_read_temp,
 };
 
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 6feb25d..8d9c689 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -183,7 +183,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static struct thermal_zone_device_ops ops = {
+static const struct thermal_zone_device_ops ops = {
 	.get_temp = armada_get_temp,
 };
 
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index b3eca71..38d6aab9 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -210,7 +210,7 @@ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
 	return -EINVAL;
 }
 
-static struct thermal_zone_device_ops thdev_ops = {
+static const struct thermal_zone_device_ops thdev_ops = {
 	.bind = db8500_cdev_bind,
 	.unbind = db8500_cdev_unbind,
 	.get_temp = db8500_sys_get_temp,
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index a0bc9de..e8fd627 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -118,7 +118,7 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static struct thermal_zone_device_ops ops = {
+static const struct thermal_zone_device_ops ops = {
 	.get_temp = dove_get_temp,
 };
 
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index f1424f0..8a3cfed 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -332,7 +332,7 @@ static int imx_unbind(struct thermal_zone_device *tz,
 	return 0;
 }
 
-static struct thermal_zone_device_ops imx_tz_ops = {
+static const struct thermal_zone_device_ops imx_tz_ops = {
 	.bind = imx_bind,
 	.unbind = imx_unbind,
 	.get_temp = imx_get_temp,
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
index 031018e..96bdf8a 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
@@ -231,7 +231,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
 	return result;
 }
 
-static struct thermal_zone_device_ops int3400_thermal_ops = {
+static const struct thermal_zone_device_ops int3400_thermal_ops = {
 	.get_temp = int3400_thermal_get_temp,
 };
 
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
index b9b2666..bd9f9e8 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
@@ -154,7 +154,7 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
 	return 0;
 }
 
-static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
+static const struct thermal_zone_device_ops int340x_thermal_zone_ops = {
 	.get_temp       = int340x_thermal_get_zone_temp,
 	.get_trip_temp	= int340x_thermal_get_trip_temp,
 	.get_trip_type	= int340x_thermal_get_trip_type,
diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
index fd550b9..625ba6f 100644
--- a/drivers/thermal/intel_soc_dts_thermal.c
+++ b/drivers/thermal/intel_soc_dts_thermal.c
@@ -270,7 +270,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 	return 0;
 }
 
-static struct thermal_zone_device_ops tzone_ops = {
+static const struct thermal_zone_device_ops tzone_ops = {
 	.get_temp = sys_get_curr_temp,
 	.get_trip_temp = sys_get_trip_temp,
 	.get_trip_type = sys_get_trip_type,
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
index 11041fe..abba3e2 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -60,7 +60,7 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static struct thermal_zone_device_ops ops = {
+static const struct thermal_zone_device_ops ops = {
 	.get_temp = kirkwood_get_temp,
 };
 
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index b9c35bd..bd3185e 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -365,7 +365,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
 	return -EINVAL;
 }
 
-static struct thermal_zone_device_ops of_thermal_ops = {
+static const struct thermal_zone_device_ops of_thermal_ops = {
 	.get_temp = of_thermal_get_temp,
 	.get_trend = of_thermal_get_trend,
 	.set_emul_temp = of_thermal_set_emul_temp,
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 5d4ae7d..320ceac 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -270,7 +270,7 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
 	return 0;
 }
 
-static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
+static const struct thermal_zone_device_ops rcar_thermal_zone_ops = {
 	.get_temp	= rcar_thermal_get_temp,
 	.get_trip_type	= rcar_thermal_get_trip_type,
 	.get_trip_temp	= rcar_thermal_get_trip_temp,
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 534dd91..ec07743 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -50,7 +50,7 @@ static inline int thermal_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static struct thermal_zone_device_ops ops = {
+static const struct thermal_zone_device_ops ops = {
 	.get_temp = thermal_get_temp,
 };
 
diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
index 44cbba9..0cb5c19 100644
--- a/drivers/thermal/st/st_thermal.c
+++ b/drivers/thermal/st/st_thermal.c
@@ -175,7 +175,7 @@ static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
 	return 0;
 }
 
-static struct thermal_zone_device_ops st_tz_ops = {
+static const struct thermal_zone_device_ops st_tz_ops = {
 	.get_temp	= st_thermal_get_temp,
 	.get_trip_type	= st_thermal_get_trip_type,
 	.get_trip_temp	= st_thermal_get_trip_temp,
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 0f3d26c..420c702 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1451,7 +1451,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
  */
 struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	int trips, int mask, void *devdata,
-	struct thermal_zone_device_ops *ops,
+	const struct thermal_zone_device_ops *ops,
 	const struct thermal_zone_params *tzp,
 	int passive_delay, int polling_delay)
 {
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index ade78eb..e9c82fc 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -281,7 +281,7 @@ static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
 	.get_trend = __ti_thermal_get_trend,
 };
 
-static struct thermal_zone_device_ops ti_thermal_ops = {
+static const struct thermal_zone_device_ops ti_thermal_ops = {
 	.get_temp = ti_thermal_get_temp,
 	.get_trend = ti_thermal_get_trend,
 	.bind = ti_thermal_bind,
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 054c6d45..bb2b975 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -274,7 +274,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
 }
 
 /* Thermal zone callback registry */
-static struct thermal_zone_device_ops tzone_ops = {
+static const struct thermal_zone_device_ops tzone_ops = {
 	.get_temp = sys_get_curr_temp,
 	.get_trip_temp = sys_get_trip_temp,
 	.get_trip_type = sys_get_trip_type,
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 5c6a589..07bd5e8 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -181,7 +181,7 @@ struct thermal_zone_device {
 	int emul_temperature;
 	int passive;
 	unsigned int forced_passive;
-	struct thermal_zone_device_ops *ops;
+	const struct thermal_zone_device_ops *ops;
 	const struct thermal_zone_params *tzp;
 	struct thermal_governor *governor;
 	struct list_head thermal_instances;
@@ -313,7 +313,7 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
 
 #if IS_ENABLED(CONFIG_THERMAL)
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
-		void *, struct thermal_zone_device_ops *,
+		void *, const struct thermal_zone_device_ops *,
 		const struct thermal_zone_params *, int, int);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
@@ -341,7 +341,7 @@ void thermal_notify_framework(struct thermal_zone_device *, int);
 #else
 static inline struct thermal_zone_device *thermal_zone_device_register(
 	const char *type, int trips, int mask, void *devdata,
-	struct thermal_zone_device_ops *ops,
+	const struct thermal_zone_device_ops *ops,
 	const struct thermal_zone_params *tzp,
 	int passive_delay, int polling_delay)
 { return ERR_PTR(-ENODEV); }
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:53 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:53 +0200
Subject: [PATCH 03/13] thermal: trivial: Add missing whitespace in message
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-4-git-send-email-s.hauer@pengutronix.de>

Commas should be followed by a whitespace.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 244784f..cecebac 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -378,7 +378,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
 
 	if (trip_type == THERMAL_TRIP_CRITICAL) {
 		dev_emerg(&tz->device,
-			  "critical temperature reached(%d C),shutting down\n",
+			  "critical temperature reached(%d C), shutting down\n",
 			  tz->temperature / 1000);
 		orderly_poweroff(true);
 	}
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:58 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:58 +0200
Subject: [PATCH 08/13] thermal: streamline get_trend callbacks
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-9-git-send-email-s.hauer@pengutronix.de>

The .get_trend callback in struct thermal_zone_device_ops has the prototype:

	int (*get_trend) (struct thermal_zone_device *, int,
			  enum thermal_trend *);

whereas the .get_trend callback in struct thermal_zone_of_device_ops has:

	int (*get_trend)(void *, long *);

Streamline both prototypes and add the trip argument to the OF callback
aswell and use enum thermal_trend * instead of an integer pointer.

While the OF prototype may be the better one, this should be decided at
framework level and not on OF level.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/of-thermal.c                       | 11 +---------
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++++---------------
 include/linux/thermal.h                            |  2 +-
 3 files changed, 10 insertions(+), 28 deletions(-)

diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 03839df..c84404d 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -187,24 +187,15 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
 				enum thermal_trend *trend)
 {
 	struct __thermal_zone *data = tz->devdata;
-	long dev_trend;
 	int r;
 
 	if (!data->ops->get_trend)
 		return -EINVAL;
 
-	r = data->ops->get_trend(data->sensor_data, &dev_trend);
+	r = data->ops->get_trend(data->sensor_data, trip, trend);
 	if (r)
 		return r;
 
-	/* TODO: These intervals might have some thresholds, but in core code */
-	if (dev_trend > 0)
-		*trend = THERMAL_TREND_RAISING;
-	else if (dev_trend < 0)
-		*trend = THERMAL_TREND_DROPPING;
-	else
-		*trend = THERMAL_TREND_STABLE;
-
 	return 0;
 }
 
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index d3a42bf..ade78eb 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -238,7 +238,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static int __ti_thermal_get_trend(void *p, long *trend)
+static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
 {
 	struct ti_thermal_data *data = p;
 	struct ti_bandgap *bgp;
@@ -251,22 +251,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
 	if (ret)
 		return ret;
 
-	*trend = tr;
-
-	return 0;
-}
-
-/* Get the temperature trend callback functions for thermal zone */
-static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
-				int trip, enum thermal_trend *trend)
-{
-	int ret;
-	long tr;
-
-	ret = __ti_thermal_get_trend(thermal->devdata, &tr);
-	if (ret)
-		return ret;
-
 	if (tr > 0)
 		*trend = THERMAL_TREND_RAISING;
 	else if (tr < 0)
@@ -277,6 +261,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
 	return 0;
 }
 
+/* Get the temperature trend callback functions for thermal zone */
+static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+				int trip, enum thermal_trend *trend)
+{
+	return __ti_thermal_get_trend(thermal->devdata, trip, trend);
+}
+
 /* Get critical temperature callback functions for thermal zone */
 static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
 				    int *temp)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index e9f2863..5c6a589 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -269,7 +269,7 @@ struct thermal_genl_event {
  */
 struct thermal_zone_of_device_ops {
 	int (*get_temp)(void *, int *);
-	int (*get_trend)(void *, long *);
+	int (*get_trend)(void *, int, enum thermal_trend *);
 	int (*set_emul_temp)(void *, int);
 };
 
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:26:00 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:26:00 +0200
Subject: [PATCH 10/13] thermal: of: always set sensor related callbacks
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-11-git-send-email-s.hauer@pengutronix.de>

Now that the thermal core treats -ENOSYS like the callbacks were
not present at all we no longer have to overwrite the ops during
runtime but instead can always set them and return -ENOSYS if no
sensor is registered.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/of-thermal.c | 33 +++++++++++++--------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index c84404d..b9c35bd 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -91,7 +91,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
 {
 	struct __thermal_zone *data = tz->devdata;
 
-	if (!data->ops->get_temp)
+	if (!data->ops)
 		return -EINVAL;
 
 	return data->ops->get_temp(data->sensor_data, temp);
@@ -178,7 +178,7 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
 	struct __thermal_zone *data = tz->devdata;
 
 	if (!data->ops || !data->ops->set_emul_temp)
-		return -EINVAL;
+		return -ENOSYS;
 
 	return data->ops->set_emul_temp(data->sensor_data, temp);
 }
@@ -189,8 +189,8 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
 	struct __thermal_zone *data = tz->devdata;
 	int r;
 
-	if (!data->ops->get_trend)
-		return -EINVAL;
+	if (!data->ops || !data->ops->get_trend)
+		return -ENOSYS;
 
 	r = data->ops->get_trend(data->sensor_data, trip, trend);
 	if (r)
@@ -366,6 +366,10 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
 }
 
 static struct thermal_zone_device_ops of_thermal_ops = {
+	.get_temp = of_thermal_get_temp,
+	.get_trend = of_thermal_get_trend,
+	.set_emul_temp = of_thermal_set_emul_temp,
+
 	.get_mode = of_thermal_get_mode,
 	.set_mode = of_thermal_set_mode,
 
@@ -399,13 +403,13 @@ thermal_zone_of_add_sensor(struct device_node *zone,
 	if (!ops)
 		return ERR_PTR(-EINVAL);
 
+	if (!ops->get_temp)
+		return ERR_PTR(-EINVAL);
+
 	mutex_lock(&tzd->lock);
 	tz->ops = ops;
 	tz->sensor_data = data;
 
-	tzd->ops->get_temp = of_thermal_get_temp;
-	tzd->ops->get_trend = of_thermal_get_trend;
-	tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
 	mutex_unlock(&tzd->lock);
 
 	return tzd;
@@ -535,9 +539,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
 		return;
 
 	mutex_lock(&tzd->lock);
-	tzd->ops->get_temp = NULL;
-	tzd->ops->get_trend = NULL;
-	tzd->ops->set_emul_temp = NULL;
 
 	tz->ops = NULL;
 	tz->sensor_data = NULL;
@@ -845,7 +846,6 @@ int __init of_parse_thermal_zones(void)
 {
 	struct device_node *np, *child;
 	struct __thermal_zone *tz;
-	struct thermal_zone_device_ops *ops;
 
 	np = of_find_node_by_name(NULL, "thermal-zones");
 	if (!np) {
@@ -869,29 +869,22 @@ int __init of_parse_thermal_zones(void)
 			continue;
 		}
 
-		ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
-		if (!ops)
-			goto exit_free;
-
 		tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
-		if (!tzp) {
-			kfree(ops);
+		if (!tzp)
 			goto exit_free;
-		}
 
 		/* No hwmon because there might be hwmon drivers registering */
 		tzp->no_hwmon = true;
 
 		zone = thermal_zone_device_register(child->name, tz->ntrips,
 						    0, tz,
-						    ops, tzp,
+						    &of_thermal_ops, tzp,
 						    tz->passive_delay,
 						    tz->polling_delay);
 		if (IS_ERR(zone)) {
 			pr_err("Failed to build %s zone %ld\n", child->name,
 			       PTR_ERR(zone));
 			kfree(tzp);
-			kfree(ops);
 			of_thermal_free_zone(tz);
 			/* attempting to build remaining zones still */
 		}
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:52 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:52 +0200
Subject: [PATCH 02/13] thermal: trivial: fix typo in comment
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-3-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Acked-by: Eduardo Valentin <edubezval at gmail.com>
---
 drivers/thermal/thermal_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 62cc82a..244784f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -402,7 +402,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 }
 
 /**
- * thermal_zone_get_temp() - returns its the temperature of thermal zone
+ * thermal_zone_get_temp() - returns the temperature of a thermal zone
  * @tz: a valid pointer to a struct thermal_zone_device
  * @temp: a valid pointer to where to store the resulting temperature.
  *
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:54 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:54 +0200
Subject: [PATCH 04/13] thermal: remove useless call to
 thermal_zone_device_set_polling
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-5-git-send-email-s.hauer@pengutronix.de>

When the thermal zone has no get_temp callback then thermal_zone_device_register()
calls thermal_zone_device_set_polling() with a polling delay of 0. This
only cancels the poll_queue. Since the poll_queue hasn't been scheduled this
is a no-op. Remove it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Acked-by: Eduardo Valentin <edubezval at gmail.com>
---
 drivers/thermal/thermal_core.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index cecebac..ad1d3c9 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1571,9 +1571,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 
 	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
 
-	if (!tz->ops->get_temp)
-		thermal_zone_device_set_polling(tz, 0);
-
 	thermal_zone_device_update(tz);
 
 	return tz;
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:26:02 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:26:02 +0200
Subject: [PATCH 12/13] thermal: thermal: Add support for hardware-tracked trip
 points
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-13-git-send-email-s.hauer@pengutronix.de>

This adds support for hardware-tracked trip points to the device tree
thermal sensor framework.

The framework supports an arbitrary number of trip points. Whenever
the current temperature is updated, the trip points immediately
below and above the current temperature are found. A .set_trips
callback is then called with the temperatures. If there is no trip
point above or below the current temperature, the passed trip
temperature will be ULONG_MAX or 0 respectively. In this callback,
the driver should program the hardware such that it is notified
when either of these trip points are triggered. When a trip point
is triggered, the driver should call `thermal_zone_device_update'
for the respective thermal zone. This will cause the trip points
to be updated again.

If .set_trips is not implemented, the framework behaves as before.

This patch is based on an earlier version from Mikko Perttunen
<mikko.perttunen at kapsi.fi>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/thermal.h        |  3 +++
 2 files changed, 45 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 420c702..4e1aaab 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -453,6 +453,45 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
 
+static void thermal_zone_set_trips(struct thermal_zone_device *tz)
+{
+	int low = -INT_MAX;
+	int high = INT_MAX;
+	int trip_temp, hysteresis;
+	int temp = tz->temperature;
+	int i;
+
+	if (!tz->ops->set_trips)
+		return;
+
+	/* No need to change trip points */
+	if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
+		return;
+
+	for (i = 0; i < tz->trips; i++) {
+		unsigned long trip_low;
+
+		tz->ops->get_trip_temp(tz, i, &trip_temp);
+		tz->ops->get_trip_hyst(tz, i, &hysteresis);
+
+		trip_low = trip_temp - hysteresis;
+
+		if (trip_low < temp && trip_low > low)
+			low = trip_low;
+
+		if (trip_temp > temp && trip_temp < high)
+			high = trip_temp;
+	}
+
+	tz->prev_low_trip = low;
+	tz->prev_high_trip = high;
+
+	dev_dbg(&tz->device, "new temperature boundaries: %d < x < %d\n",
+			low, high);
+
+	tz->ops->set_trips(tz, low, high);
+}
+
 void thermal_zone_device_update(struct thermal_zone_device *tz)
 {
 	int temp, ret, count;
@@ -473,6 +512,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 	mutex_lock(&tz->lock);
 	tz->last_temperature = tz->temperature;
 	tz->temperature = temp;
+	thermal_zone_set_trips(tz);
 	mutex_unlock(&tz->lock);
 
 	trace_thermal_temperature(tz);
@@ -1494,6 +1534,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	tz->trips = trips;
 	tz->passive_delay = passive_delay;
 	tz->polling_delay = polling_delay;
+	tz->prev_low_trip = INT_MAX;
+	tz->prev_high_trip = -INT_MAX;
 
 	dev_set_name(&tz->device, "thermal_zone%d", tz->id);
 	result = device_register(&tz->device);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 07bd5e8..aef6e13 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
 	int (*unbind) (struct thermal_zone_device *,
 		       struct thermal_cooling_device *);
 	int (*get_temp) (struct thermal_zone_device *, int *);
+	int (*set_trips) (struct thermal_zone_device *, int, int);
 	int (*get_mode) (struct thermal_zone_device *,
 			 enum thermal_device_mode *);
 	int (*set_mode) (struct thermal_zone_device *,
@@ -180,6 +181,8 @@ struct thermal_zone_device {
 	int last_temperature;
 	int emul_temperature;
 	int passive;
+	int prev_low_trip;
+	int prev_high_trip;
 	unsigned int forced_passive;
 	const struct thermal_zone_device_ops *ops;
 	const struct thermal_zone_params *tzp;
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:26:03 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:26:03 +0200
Subject: [PATCH 13/13] thermal: of: implement .set_trips for device tree
 thermal zones
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-14-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/of-thermal.c | 12 ++++++++++++
 include/linux/thermal.h      |  3 +++
 2 files changed, 15 insertions(+)

diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index bd3185e..f8dd847 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -97,6 +97,17 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
 	return data->ops->get_temp(data->sensor_data, temp);
 }
 
+static int of_thermal_set_trips(struct thermal_zone_device *tz,
+			       int low, int high)
+{
+	struct __thermal_zone *data = tz->devdata;
+
+	if (!data->ops || !data->ops->set_trips)
+		return -ENOSYS;
+
+	return data->ops->set_trips(data->sensor_data, low, high);
+}
+
 /**
  * of_thermal_get_ntrips - function to export number of available trip
  *			   points.
@@ -367,6 +378,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
 
 static const struct thermal_zone_device_ops of_thermal_ops = {
 	.get_temp = of_thermal_get_temp,
+	.set_trips = of_thermal_set_trips,
 	.get_trend = of_thermal_get_trend,
 	.set_emul_temp = of_thermal_set_emul_temp,
 
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index aef6e13..b751f6b 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -267,12 +267,15 @@ struct thermal_genl_event {
  *
  * Optional:
  * @get_trend: a pointer to a function that reads the sensor temperature trend.
+ * @set_trips: a pointer to a function that sets a temperature window which shall
+ *             trigger an interrupt when it is left.
  * @set_emul_temp: a pointer to a function that sets sensor emulated
  *		   temperature.
  */
 struct thermal_zone_of_device_ops {
 	int (*get_temp)(void *, int *);
 	int (*get_trend)(void *, int, enum thermal_trend *);
+	int (*set_trips)(void *, int, int);
 	int (*set_emul_temp)(void *, int);
 };
 
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:51 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:51 +0200
Subject: [PATCH 01/13] thermal: consistently use int for temperatures
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-2-git-send-email-s.hauer@pengutronix.de>

The thermal code uses int, long and unsigned long for temperatures
in different places. Using an unsigned type limits the thermal framework
to positive temperatures without need. 'long' is 64bit on several
architectures which is not needed. Consistently use a plain 'int'
for temperatures.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/acpi/thermal.c                             | 12 +++++-----
 drivers/hwmon/lm75.c                               |  2 +-
 drivers/hwmon/ntc_thermistor.c                     |  2 +-
 drivers/hwmon/tmp102.c                             |  2 +-
 drivers/input/touchscreen/sun4i-ts.c               |  8 +++----
 drivers/platform/x86/acerhdf.c                     |  9 ++++----
 drivers/power/power_supply_core.c                  |  2 +-
 drivers/thermal/armada_thermal.c                   |  2 +-
 drivers/thermal/db8500_thermal.c                   |  7 +++---
 drivers/thermal/dove_thermal.c                     |  2 +-
 drivers/thermal/fair_share.c                       |  2 +-
 drivers/thermal/gov_bang_bang.c                    |  5 ++--
 drivers/thermal/imx_thermal.c                      | 27 +++++++++++-----------
 .../thermal/int340x_thermal/int340x_thermal_zone.c | 10 ++++----
 .../thermal/int340x_thermal/int340x_thermal_zone.h |  8 +++----
 drivers/thermal/intel_soc_dts_thermal.c            |  7 +++---
 drivers/thermal/of-thermal.c                       | 14 +++++------
 drivers/thermal/rcar_thermal.c                     |  7 +++---
 drivers/thermal/rockchip_thermal.c                 | 10 ++++----
 drivers/thermal/samsung/exynos_tmu.c               | 19 ++++++++-------
 drivers/thermal/spear_thermal.c                    |  2 +-
 drivers/thermal/st/st_thermal.c                    |  5 ++--
 drivers/thermal/step_wise.c                        |  4 ++--
 drivers/thermal/tegra_soctherm.c                   |  4 ++--
 drivers/thermal/thermal_core.c                     | 26 ++++++++++-----------
 drivers/thermal/thermal_hwmon.c                    | 10 ++++----
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 10 ++++----
 drivers/thermal/x86_pkg_temp_thermal.c             | 10 ++++----
 include/linux/thermal.h                            | 26 +++++++++------------
 29 files changed, 120 insertions(+), 134 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index d24fa19..68bff60 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -529,8 +529,7 @@ static void acpi_thermal_check(void *data)
 
 /* sys I/F for generic thermal sysfs support */
 
-static int thermal_get_temp(struct thermal_zone_device *thermal,
-			    unsigned long *temp)
+static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
 {
 	struct acpi_thermal *tz = thermal->devdata;
 	int result;
@@ -637,7 +636,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
 }
 
 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
-				 int trip, unsigned long *temp)
+				 int trip, int *temp)
 {
 	struct acpi_thermal *tz = thermal->devdata;
 	int i;
@@ -690,7 +689,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 }
 
 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
-				unsigned long *temperature) {
+				int *temperature)
+{
 	struct acpi_thermal *tz = thermal->devdata;
 
 	if (tz->trips.critical.flags.valid) {
@@ -713,8 +713,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
 		return -EINVAL;
 
 	if (type == THERMAL_TRIP_ACTIVE) {
-		unsigned long trip_temp;
-		unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
+		int trip_temp;
+		int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
 					tz->temperature, tz->kelvin_offset);
 		if (thermal_get_trip_temp(thermal, trip, &trip_temp))
 			return -EINVAL;
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index fe41d5a..e4e57bb 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -104,7 +104,7 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
 
 /* sysfs attributes for hwmon */
 
-static int lm75_read_temp(void *dev, long *temp)
+static int lm75_read_temp(void *dev, int *temp)
 {
 	struct lm75_data *data = lm75_update_device(dev);
 
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 112e4d4..9f085df 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -430,7 +430,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
 	return -EINVAL;
 }
 
-static int ntc_read_temp(void *dev, long *temp)
+static int ntc_read_temp(void *dev, int *temp)
 {
 	struct ntc_data *data = dev_get_drvdata(dev);
 	int ohm;
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 9da2735..6548262 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -98,7 +98,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
 	return tmp102;
 }
 
-static int tmp102_read_temp(void *dev, long *temp)
+static int tmp102_read_temp(void *dev, int *temp)
 {
 	struct tmp102 *tmp102 = tmp102_update_device(dev);
 
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index c011699..4857943 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -191,7 +191,7 @@ static void sun4i_ts_close(struct input_dev *dev)
 	writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
 }
 
-static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
+static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp)
 {
 	/* No temp_data until the first irq */
 	if (ts->temp_data == -1)
@@ -202,7 +202,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
 	return 0;
 }
 
-static int sun4i_get_tz_temp(void *data, long *temp)
+static int sun4i_get_tz_temp(void *data, int *temp)
 {
 	return sun4i_get_temp(data, temp);
 }
@@ -215,14 +215,14 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
 			 char *buf)
 {
 	struct sun4i_ts_data *ts = dev_get_drvdata(dev);
-	long temp;
+	int temp;
 	int error;
 
 	error = sun4i_get_temp(ts, &temp);
 	if (error)
 		return error;
 
-	return sprintf(buf, "%ld\n", temp);
+	return sprintf(buf, "%d\n", temp);
 }
 
 static ssize_t show_temp_label(struct device *dev,
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 594c918..f2ce63c 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -346,8 +346,7 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
  * as late as the polling interval is since we can't do that in the respective
  * accessors of the module parameters.
  */
-static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal,
-			       unsigned long *t)
+static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t)
 {
 	int temp, err = 0;
 
@@ -452,7 +451,7 @@ static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
 }
 
 static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
-				 unsigned long *temp)
+				 int *temp)
 {
 	if (trip != 0)
 		return -EINVAL;
@@ -463,7 +462,7 @@ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
 }
 
 static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
-				 unsigned long *temp)
+				 int *temp)
 {
 	if (trip == 0)
 		*temp = fanon;
@@ -476,7 +475,7 @@ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
 }
 
 static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
-				 unsigned long *temperature)
+				 int *temperature)
 {
 	*temperature = ACERHDF_TEMP_CRIT;
 	return 0;
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 2ed4a4a..87e2fd1 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -492,7 +492,7 @@ EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
 
 #ifdef CONFIG_THERMAL
 static int power_supply_read_temp(struct thermal_zone_device *tzd,
-		unsigned long *temp)
+		int *temp)
 {
 	struct power_supply *psy;
 	union power_supply_propval val;
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index c2556cf..6feb25d 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -155,7 +155,7 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
 }
 
 static int armada_get_temp(struct thermal_zone_device *thermal,
-			  unsigned long *temp)
+			  int *temp)
 {
 	struct armada_thermal_priv *priv = thermal->devdata;
 	unsigned long reg;
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 20adfbe..b3eca71 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -107,8 +107,7 @@ static int db8500_cdev_unbind(struct thermal_zone_device *thermal,
 }
 
 /* Callback to get current temperature */
-static int db8500_sys_get_temp(struct thermal_zone_device *thermal,
-		unsigned long *temp)
+static int db8500_sys_get_temp(struct thermal_zone_device *thermal, int *temp)
 {
 	struct db8500_thermal_zone *pzone = thermal->devdata;
 
@@ -180,7 +179,7 @@ static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal,
 
 /* Callback to get trip point temperature */
 static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
-		int trip, unsigned long *temp)
+		int trip, int *temp)
 {
 	struct db8500_thermal_zone *pzone = thermal->devdata;
 	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
@@ -195,7 +194,7 @@ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
 
 /* Callback to get critical trip point temperature */
 static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
-		unsigned long *temp)
+		int *temp)
 {
 	struct db8500_thermal_zone *pzone = thermal->devdata;
 	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index 09f6e30..a0bc9de 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -93,7 +93,7 @@ static int dove_init_sensor(const struct dove_thermal_priv *priv)
 }
 
 static int dove_get_temp(struct thermal_zone_device *thermal,
-			  unsigned long *temp)
+			  int *temp)
 {
 	unsigned long reg;
 	struct dove_thermal_priv *priv = thermal->devdata;
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
index 6e0a3fb..efad70e 100644
--- a/drivers/thermal/fair_share.c
+++ b/drivers/thermal/fair_share.c
@@ -34,7 +34,7 @@
 static int get_trip_level(struct thermal_zone_device *tz)
 {
 	int count = 0;
-	unsigned long trip_temp;
+	int trip_temp;
 	enum thermal_trip_type trip_type;
 
 	if (tz->trips == 0 || !tz->ops->get_trip_temp)
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
index c5dd76b..70836c5 100644
--- a/drivers/thermal/gov_bang_bang.c
+++ b/drivers/thermal/gov_bang_bang.c
@@ -25,14 +25,13 @@
 
 static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 {
-	long trip_temp;
-	unsigned long trip_hyst;
+	int trip_temp, trip_hyst;
 	struct thermal_instance *instance;
 
 	tz->ops->get_trip_temp(tz, trip, &trip_temp);
 	tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
 
-	dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n",
+	dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
 				trip, trip_temp, tz->temperature,
 				trip_hyst);
 
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 2ccbc07..f1424f0 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -98,10 +98,10 @@ struct imx_thermal_data {
 	enum thermal_device_mode mode;
 	struct regmap *tempmon;
 	u32 c1, c2; /* See formula in imx_get_sensor_data() */
-	unsigned long temp_passive;
-	unsigned long temp_critical;
-	unsigned long alarm_temp;
-	unsigned long last_temp;
+	int temp_passive;
+	int temp_critical;
+	int alarm_temp;
+	int last_temp;
 	bool irq_enabled;
 	int irq;
 	struct clk *thermal_clk;
@@ -109,7 +109,7 @@ struct imx_thermal_data {
 };
 
 static void imx_set_panic_temp(struct imx_thermal_data *data,
-			       signed long panic_temp)
+			       int panic_temp)
 {
 	struct regmap *map = data->tempmon;
 	int critical_value;
@@ -121,7 +121,7 @@ static void imx_set_panic_temp(struct imx_thermal_data *data,
 }
 
 static void imx_set_alarm_temp(struct imx_thermal_data *data,
-			       signed long alarm_temp)
+			       int alarm_temp)
 {
 	struct regmap *map = data->tempmon;
 	int alarm_value;
@@ -133,7 +133,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
 			TEMPSENSE0_ALARM_VALUE_SHIFT);
 }
 
-static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
+static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
 {
 	struct imx_thermal_data *data = tz->devdata;
 	struct regmap *map = data->tempmon;
@@ -189,13 +189,13 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
 		if (data->alarm_temp == data->temp_critical &&
 			*temp < data->temp_passive) {
 			imx_set_alarm_temp(data, data->temp_passive);
-			dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
+			dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
 				data->alarm_temp / 1000);
 		}
 	}
 
 	if (*temp != data->last_temp) {
-		dev_dbg(&tz->device, "millicelsius: %ld\n", *temp);
+		dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
 		data->last_temp = *temp;
 	}
 
@@ -262,8 +262,7 @@ static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
 	return 0;
 }
 
-static int imx_get_crit_temp(struct thermal_zone_device *tz,
-			     unsigned long *temp)
+static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
 {
 	struct imx_thermal_data *data = tz->devdata;
 
@@ -272,7 +271,7 @@ static int imx_get_crit_temp(struct thermal_zone_device *tz,
 }
 
 static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
-			     unsigned long *temp)
+			     int *temp)
 {
 	struct imx_thermal_data *data = tz->devdata;
 
@@ -282,7 +281,7 @@ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
 }
 
 static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
-			     unsigned long temp)
+			     int temp)
 {
 	struct imx_thermal_data *data = tz->devdata;
 
@@ -433,7 +432,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
 {
 	struct imx_thermal_data *data = dev;
 
-	dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
+	dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
 		data->alarm_temp / 1000);
 
 	thermal_zone_device_update(data->tz);
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
index 1e25133..b9b2666 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
@@ -20,7 +20,7 @@
 #include "int340x_thermal_zone.h"
 
 static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
-					 unsigned long *temp)
+					 int *temp)
 {
 	struct int34x_thermal_zone *d = zone->devdata;
 	unsigned long long tmp;
@@ -49,7 +49,7 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
 }
 
 static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
-					 int trip, unsigned long *temp)
+					 int trip, int *temp)
 {
 	struct int34x_thermal_zone *d = zone->devdata;
 	int i;
@@ -114,7 +114,7 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
 }
 
 static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
-				      int trip, unsigned long temp)
+				      int trip, int temp)
 {
 	struct int34x_thermal_zone *d = zone->devdata;
 	acpi_status status;
@@ -136,7 +136,7 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
 
 
 static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
-		int trip, unsigned long *temp)
+		int trip, int *temp)
 {
 	struct int34x_thermal_zone *d = zone->devdata;
 	acpi_status status;
@@ -163,7 +163,7 @@ static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
 };
 
 static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
-				      unsigned long *temp)
+				      int *temp)
 {
 	unsigned long long r;
 	acpi_status status;
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
index 9f38ab7..aaadf72 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
@@ -21,7 +21,7 @@
 #define INT340X_THERMAL_MAX_ACT_TRIP_COUNT	10
 
 struct active_trip {
-	unsigned long temp;
+	int temp;
 	int id;
 	bool valid;
 };
@@ -31,11 +31,11 @@ struct int34x_thermal_zone {
 	struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT];
 	unsigned long *aux_trips;
 	int aux_trip_nr;
-	unsigned long psv_temp;
+	int psv_temp;
 	int psv_trip_id;
-	unsigned long crt_temp;
+	int crt_temp;
 	int crt_trip_id;
-	unsigned long hot_temp;
+	int hot_temp;
 	int hot_trip_id;
 	struct thermal_zone_device *zone;
 	struct thermal_zone_device_ops *override_ops;
diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
index 9013505..fd550b9 100644
--- a/drivers/thermal/intel_soc_dts_thermal.c
+++ b/drivers/thermal/intel_soc_dts_thermal.c
@@ -106,7 +106,7 @@ err_ret:
 }
 
 static int sys_get_trip_temp(struct thermal_zone_device *tzd,
-					int trip, unsigned long *temp)
+					int trip, int *temp)
 {
 	int status;
 	u32 out;
@@ -224,7 +224,7 @@ err_restore_ptps:
 }
 
 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
-							unsigned long temp)
+							int temp)
 {
 	struct soc_sensor_entry *aux_entry = tzd->devdata;
 	int status;
@@ -250,8 +250,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static int sys_get_curr_temp(struct thermal_zone_device *tzd,
-						unsigned long *temp)
+static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 {
 	int status;
 	u32 out;
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 668fb1b..03839df 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -87,7 +87,7 @@ struct __thermal_zone {
 /***   DT thermal zone device callbacks   ***/
 
 static int of_thermal_get_temp(struct thermal_zone_device *tz,
-			       unsigned long *temp)
+			       int *temp)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -173,7 +173,7 @@ EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
  * Return: zero on success, error code otherwise
  */
 static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
-				    unsigned long temp)
+				    int temp)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -306,7 +306,7 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
 }
 
 static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
-				    unsigned long *temp)
+				    int *temp)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -319,7 +319,7 @@ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
 }
 
 static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
-				    unsigned long temp)
+				    int temp)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -333,7 +333,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
 }
 
 static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
-				    unsigned long *hyst)
+				    int *hyst)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -346,7 +346,7 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
 }
 
 static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
-				    unsigned long hyst)
+				    int hyst)
 {
 	struct __thermal_zone *data = tz->devdata;
 
@@ -360,7 +360,7 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
 }
 
 static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
-				    unsigned long *temp)
+				    int *temp)
 {
 	struct __thermal_zone *data = tz->devdata;
 	int i;
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index fe4e767..5d4ae7d 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -200,8 +200,7 @@ err_out_unlock:
 	return ret;
 }
 
-static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
-				 unsigned long *temp)
+static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
 {
 	struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
 
@@ -235,7 +234,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
 }
 
 static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
-				      int trip, unsigned long *temp)
+				      int trip, int *temp)
 {
 	struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
 	struct device *dev = rcar_priv_to_dev(priv);
@@ -299,7 +298,7 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
 static void rcar_thermal_work(struct work_struct *work)
 {
 	struct rcar_thermal_priv *priv;
-	unsigned long cctemp, nctemp;
+	int cctemp, nctemp;
 
 	priv = container_of(work, struct rcar_thermal_priv, work.work);
 
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 3aa46ac..0cc219c 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -64,7 +64,7 @@ struct rockchip_tsadc_chip {
 	void (*control)(void __iomem *reg, bool on);
 
 	/* Per-sensor methods */
-	int (*get_temp)(int chn, void __iomem *reg, long *temp);
+	int (*get_temp)(int chn, void __iomem *reg, int *temp);
 	void (*set_tshut_temp)(int chn, void __iomem *reg, long temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
 };
@@ -191,7 +191,7 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
 	return 0;
 }
 
-static long rk_tsadcv2_code_to_temp(u32 code)
+static int rk_tsadcv2_code_to_temp(u32 code)
 {
 	unsigned int low = 0;
 	unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
@@ -277,7 +277,7 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable)
 	writel_relaxed(val, regs + TSADCV2_AUTO_CON);
 }
 
-static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, long *temp)
+static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp)
 {
 	u32 val;
 
@@ -366,7 +366,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
+static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 {
 	struct rockchip_thermal_sensor *sensor = _sensor;
 	struct rockchip_thermal_data *thermal = sensor->thermal;
@@ -374,7 +374,7 @@ static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
 	int retval;
 
 	retval = tsadc->get_temp(sensor->id, thermal->regs, out_temp);
-	dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %ld, retval: %d\n",
+	dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
 		sensor->id, *out_temp, retval);
 
 	return retval;
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 1d30b09..29eaf4d 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -181,8 +181,7 @@ struct exynos_tmu_data {
 	int (*tmu_initialize)(struct platform_device *pdev);
 	void (*tmu_control)(struct platform_device *pdev, bool on);
 	int (*tmu_read)(struct exynos_tmu_data *data);
-	void (*tmu_set_emulation)(struct exynos_tmu_data *data,
-				  unsigned long temp);
+	void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
 	void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
 };
 
@@ -190,7 +189,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p)
 {
 	char data[10], *envp[] = { data, NULL };
 	struct thermal_zone_device *tz = p->tzd;
-	unsigned long temp;
+	int temp;
 	unsigned int i;
 
 	if (!tz) {
@@ -489,7 +488,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	unsigned int trim_info = 0, con, rising_threshold;
 	int ret = 0, threshold_code;
-	unsigned long crit_temp = 0;
+	int crit_temp = 0;
 
 	/*
 	 * For exynos5440 soc triminfo value is swapped between TMU0 and
@@ -542,7 +541,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev)
 	unsigned int status, trim_info;
 	unsigned int rising_threshold = 0, falling_threshold = 0;
 	int ret = 0, threshold_code, i;
-	unsigned long temp, temp_hist;
+	int temp, temp_hist;
 	unsigned int reg_off, bit_off;
 
 	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
@@ -713,7 +712,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
 	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
 }
 
-static int exynos_get_temp(void *p, long *temp)
+static int exynos_get_temp(void *p, int *temp)
 {
 	struct exynos_tmu_data *data = p;
 
@@ -733,7 +732,7 @@ static int exynos_get_temp(void *p, long *temp)
 
 #ifdef CONFIG_THERMAL_EMULATION
 static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
-			    unsigned long temp)
+			    int temp)
 {
 	if (temp) {
 		temp /= MCELSIUS;
@@ -763,7 +762,7 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
 }
 
 static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
-					 unsigned long temp)
+					 int temp)
 {
 	unsigned int val;
 	u32 emul_con;
@@ -781,7 +780,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
 }
 
 static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
-					 unsigned long temp)
+					 int temp)
 {
 	unsigned int val;
 
@@ -790,7 +789,7 @@ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
 	writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
 }
 
-static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
+static int exynos_tmu_set_emulation(void *drv_data, int temp)
 {
 	struct exynos_tmu_data *data = drv_data;
 	int ret = -EINVAL;
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index bddb717..534dd91 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -38,7 +38,7 @@ struct spear_thermal_dev {
 };
 
 static inline int thermal_get_temp(struct thermal_zone_device *thermal,
-				unsigned long *temp)
+				int *temp)
 {
 	struct spear_thermal_dev *stdev = thermal->devdata;
 
diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
index 76c515d..44cbba9 100644
--- a/drivers/thermal/st/st_thermal.c
+++ b/drivers/thermal/st/st_thermal.c
@@ -111,8 +111,7 @@ static int st_thermal_calibration(struct st_thermal_sensor *sensor)
 }
 
 /* Callback to get temperature from HW*/
-static int st_thermal_get_temp(struct thermal_zone_device *th,
-		unsigned long *temperature)
+static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature)
 {
 	struct st_thermal_sensor *sensor = th->devdata;
 	struct device *dev = sensor->dev;
@@ -159,7 +158,7 @@ static int st_thermal_get_trip_type(struct thermal_zone_device *th,
 }
 
 static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
-				    int trip, unsigned long *temp)
+				    int trip, int *temp)
 {
 	struct st_thermal_sensor *sensor = th->devdata;
 	struct device *dev = sensor->dev;
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index 5a0f12d..2f9f708 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -113,7 +113,7 @@ static void update_passive_instance(struct thermal_zone_device *tz,
 
 static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 {
-	long trip_temp;
+	int trip_temp;
 	enum thermal_trip_type trip_type;
 	enum thermal_trend trend;
 	struct thermal_instance *instance;
@@ -135,7 +135,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 		trace_thermal_zone_trip(tz, trip, trip_type);
 	}
 
-	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
+	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
 				trip, trip_type, trip_temp, trend, throttle);
 
 	mutex_lock(&tz->lock);
diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c
index 9197fc0..74ea576 100644
--- a/drivers/thermal/tegra_soctherm.c
+++ b/drivers/thermal/tegra_soctherm.c
@@ -293,7 +293,7 @@ static int enable_tsensor(struct tegra_soctherm *tegra,
  * H denotes an addition of 0.5 Celsius and N denotes negation
  * of the final value.
  */
-static long translate_temp(u16 val)
+static int translate_temp(u16 val)
 {
 	long t;
 
@@ -306,7 +306,7 @@ static long translate_temp(u16 val)
 	return t;
 }
 
-static int tegra_thermctl_get_temp(void *data, long *out_temp)
+static int tegra_thermctl_get_temp(void *data, int *out_temp)
 {
 	struct tegra_thermctl_zone *zone = data;
 	u32 val;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4108db7..62cc82a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -363,7 +363,7 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
 static void handle_critical_trips(struct thermal_zone_device *tz,
 				int trip, enum thermal_trip_type trip_type)
 {
-	long trip_temp;
+	int trip_temp;
 
 	tz->ops->get_trip_temp(tz, trip, &trip_temp);
 
@@ -411,12 +411,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
  *
  * Return: On success returns 0, an error code otherwise
  */
-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
+int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 {
 	int ret = -EINVAL;
 #ifdef CONFIG_THERMAL_EMULATION
 	int count;
-	unsigned long crit_temp = -1UL;
+	int crit_temp = INT_MAX;
 	enum thermal_trip_type type;
 #endif
 
@@ -453,8 +453,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
 
 static void update_temperature(struct thermal_zone_device *tz)
 {
-	long temp;
-	int ret;
+	int temp, ret;
 
 	ret = thermal_zone_get_temp(tz, &temp);
 	if (ret) {
@@ -514,15 +513,14 @@ static ssize_t
 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
-	long temperature;
-	int ret;
+	int temperature, ret;
 
 	ret = thermal_zone_get_temp(tz, &temperature);
 
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%ld\n", temperature);
+	return sprintf(buf, "%d\n", temperature);
 }
 
 static ssize_t
@@ -626,7 +624,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 {
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
 	int trip, ret;
-	long temperature;
+	int temperature;
 
 	if (!tz->ops->get_trip_temp)
 		return -EPERM;
@@ -639,7 +637,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%ld\n", temperature);
+	return sprintf(buf, "%d\n", temperature);
 }
 
 static ssize_t
@@ -648,7 +646,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
 {
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
 	int trip, ret;
-	unsigned long temperature;
+	int temperature;
 
 	if (!tz->ops->set_trip_hyst)
 		return -EPERM;
@@ -656,7 +654,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
 	if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
 		return -EINVAL;
 
-	if (kstrtoul(buf, 10, &temperature))
+	if (kstrtoint(buf, 10, &temperature))
 		return -EINVAL;
 
 	/*
@@ -675,7 +673,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
 {
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
 	int trip, ret;
-	unsigned long temperature;
+	int temperature;
 
 	if (!tz->ops->get_trip_hyst)
 		return -EPERM;
@@ -685,7 +683,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
 
 	ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
 
-	return ret ? ret : sprintf(buf, "%ld\n", temperature);
+	return ret ? ret : sprintf(buf, "%d\n", temperature);
 }
 
 static ssize_t
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index 1967bee..06fd2ed9 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -69,7 +69,7 @@ static DEVICE_ATTR(name, 0444, name_show, NULL);
 static ssize_t
 temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	long temperature;
+	int temperature;
 	int ret;
 	struct thermal_hwmon_attr *hwmon_attr
 			= container_of(attr, struct thermal_hwmon_attr, attr);
@@ -83,7 +83,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%ld\n", temperature);
+	return sprintf(buf, "%d\n", temperature);
 }
 
 static ssize_t
@@ -95,14 +95,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
 			= container_of(hwmon_attr, struct thermal_hwmon_temp,
 				       temp_crit);
 	struct thermal_zone_device *tz = temp->tz;
-	long temperature;
+	int temperature;
 	int ret;
 
 	ret = tz->ops->get_trip_temp(tz, 0, &temperature);
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%ld\n", temperature);
+	return sprintf(buf, "%d\n", temperature);
 }
 
 
@@ -142,7 +142,7 @@ thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
 
 static bool thermal_zone_crit_temp_valid(struct thermal_zone_device *tz)
 {
-	unsigned long temp;
+	int temp;
 	return tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, &temp);
 }
 
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index a38c175..d3a42bf 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -76,14 +76,14 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 
 /* thermal zone ops */
 /* Get temperature callback function for thermal zone*/
-static inline int __ti_thermal_get_temp(void *devdata, long *temp)
+static inline int __ti_thermal_get_temp(void *devdata, int *temp)
 {
 	struct thermal_zone_device *pcb_tz = NULL;
 	struct ti_thermal_data *data = devdata;
 	struct ti_bandgap *bgp;
 	const struct ti_temp_sensor *s;
 	int ret, tmp, slope, constant;
-	unsigned long pcb_temp;
+	int pcb_temp;
 
 	if (!data)
 		return 0;
@@ -119,7 +119,7 @@ static inline int __ti_thermal_get_temp(void *devdata, long *temp)
 }
 
 static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
-				      unsigned long *temp)
+				      int *temp)
 {
 	struct ti_thermal_data *data = thermal->devdata;
 
@@ -228,7 +228,7 @@ static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
 
 /* Get trip temperature callback functions for thermal zone */
 static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
-				    int trip, unsigned long *temp)
+				    int trip, int *temp)
 {
 	if (!ti_thermal_is_valid_trip(trip))
 		return -EINVAL;
@@ -279,7 +279,7 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
 
 /* Get critical temperature callback functions for thermal zone */
 static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
-				    unsigned long *temp)
+				    int *temp)
 {
 	/* shutdown zone */
 	return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 9ea3d9d..054c6d45 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -164,7 +164,7 @@ err_ret:
 	return err;
 }
 
-static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 {
 	u32 eax, edx;
 	struct phy_dev_entry *phy_dev_entry;
@@ -175,7 +175,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
 	if (eax & 0x80000000) {
 		*temp = phy_dev_entry->tj_max -
 				((eax >> 16) & 0x7f) * 1000;
-		pr_debug("sys_get_curr_temp %ld\n", *temp);
+		pr_debug("sys_get_curr_temp %d\n", *temp);
 		return 0;
 	}
 
@@ -183,7 +183,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
 }
 
 static int sys_get_trip_temp(struct thermal_zone_device *tzd,
-		int trip, unsigned long *temp)
+		int trip, int *temp)
 {
 	u32 eax, edx;
 	struct phy_dev_entry *phy_dev_entry;
@@ -214,13 +214,13 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
 		*temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
 	else
 		*temp = 0;
-	pr_debug("sys_get_trip_temp %ld\n", *temp);
+	pr_debug("sys_get_trip_temp %d\n", *temp);
 
 	return 0;
 }
 
 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
-							unsigned long temp)
+							int temp)
 {
 	u32 l, h;
 	struct phy_dev_entry *phy_dev_entry;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 5eac316..e9f2863 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -86,23 +86,19 @@ struct thermal_zone_device_ops {
 		     struct thermal_cooling_device *);
 	int (*unbind) (struct thermal_zone_device *,
 		       struct thermal_cooling_device *);
-	int (*get_temp) (struct thermal_zone_device *, unsigned long *);
+	int (*get_temp) (struct thermal_zone_device *, int *);
 	int (*get_mode) (struct thermal_zone_device *,
 			 enum thermal_device_mode *);
 	int (*set_mode) (struct thermal_zone_device *,
 		enum thermal_device_mode);
 	int (*get_trip_type) (struct thermal_zone_device *, int,
 		enum thermal_trip_type *);
-	int (*get_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long *);
-	int (*set_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long);
-	int (*get_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long *);
-	int (*set_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long);
-	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
-	int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
+	int (*get_trip_temp) (struct thermal_zone_device *, int, int *);
+	int (*set_trip_temp) (struct thermal_zone_device *, int, int);
+	int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
+	int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
+	int (*get_crit_temp) (struct thermal_zone_device *, int *);
+	int (*set_emul_temp) (struct thermal_zone_device *, int);
 	int (*get_trend) (struct thermal_zone_device *, int,
 			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
@@ -272,9 +268,9 @@ struct thermal_genl_event {
  *		   temperature.
  */
 struct thermal_zone_of_device_ops {
-	int (*get_temp)(void *, long *);
+	int (*get_temp)(void *, int *);
 	int (*get_trend)(void *, long *);
-	int (*set_emul_temp)(void *, unsigned long);
+	int (*set_emul_temp)(void *, int);
 };
 
 /**
@@ -335,7 +331,7 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
 				   const struct thermal_cooling_device_ops *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
+int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
 
 int get_tz_trend(struct thermal_zone_device *, int);
 struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -378,7 +374,7 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
 		const char *name)
 { return ERR_PTR(-ENODEV); }
 static inline int thermal_zone_get_temp(
-		struct thermal_zone_device *tz, unsigned long *temp)
+		struct thermal_zone_device *tz, int *temp)
 { return -ENODEV; }
 static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
 { return -ENODEV; }
-- 
2.1.4



From eddie.huang at mediatek.com  Tue Apr 28 01:31:07 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 16:31:07 +0800
Subject: [PATCH v6 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
In-Reply-To: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430209869-6631-2-git-send-email-eddie.huang@mediatek.com>

From: Xudong Chen <xudong.chen at mediatek.com>

Add devicetree bindings for Mediatek Soc I2C driver.

Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
new file mode 100644
index 0000000..0ce6fa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
@@ -0,0 +1,41 @@
+* Mediatek's I2C controller
+
+The Mediatek's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
+      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
+      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
+      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
+      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
+  - reg: physical base address of the controller and dma base, length of memory
+    mapped region.
+  - interrupts: interrupt number to the cpu.
+  - clock-div: the fixed value for frequency divider of clock source in i2c
+    module. Each IC may be different.
+  - clocks: clock name from clock manager
+  - clock-names: Must include "main" and "dma", if enable have-pmic need include
+    "pmic" extra.
+
+Optional properties:
+  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
+    is 100000.
+  - mediatek,have-pmic: platform can control i2c form special pmic side.
+    Only mt6589 and mt8135 support this feature.
+  - mediatek,use-push-pull: IO config use push-pull mode.
+
+Example:
+
+	i2c0: i2c at 1100d000 {
+			compatible = "mediatek,mt6577-i2c";
+			reg = <0x1100d000 0x70>,
+			      <0x11000300 0x80>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <400000>;
+			mediatek,have-pmic;
+			clock-div = <16>;
+			clocks = <&i2c0_ck>, <&ap_dma_ck>;
+			clock-names = "main", "dma";
+	};
+
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 01:31:09 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 16:31:09 +0800
Subject: [PATCH v6 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C
 controller
In-Reply-To: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430209869-6631-4-git-send-email-eddie.huang@mediatek.com>

Add mediatek MT8173 I2C controller driver. Compare to I2C controller
of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
also increase message size to 64kb.

Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/i2c/busses/i2c-mt65xx.c | 106 +++++++++++++++++++++++++++++-----------
 1 file changed, 77 insertions(+), 29 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 2ecf0d1..c501421 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -33,10 +33,13 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 
+#define I2C_RS_TRANSFER			(1 << 4)
 #define I2C_HS_NACKERR			(1 << 2)
 #define I2C_ACKERR			(1 << 1)
 #define I2C_TRANSAC_COMP		(1 << 0)
 #define I2C_TRANSAC_START		(1 << 0)
+#define I2C_RS_MUL_CNFG			(1 << 15)
+#define I2C_RS_MUL_TRIG			(1 << 14)
 #define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
 #define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
 #define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
@@ -67,6 +70,9 @@
 #define MAX_MSG_NUM_MT6577		1
 #define MAX_DMA_TRANS_SIZE_MT6577	255
 #define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_MSG_NUM_MT8173		65535
+#define MAX_DMA_TRANS_SIZE_MT8173	65535
+#define MAX_WRRD_TRANS_SIZE_MT8173	65535
 #define MAX_SAMPLE_CNT_DIV		8
 #define MAX_STEP_CNT_DIV		64
 #define MAX_HS_STEP_CNT_DIV		8
@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
 	const struct i2c_adapter_quirks *quirks;
 	unsigned char pmic_i2c;
 	unsigned char dcm;
+	unsigned char auto_restart;
 };
 
 struct mtk_i2c {
@@ -172,24 +179,42 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
 	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
 };
 
+static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
+	.max_num_msgs = MAX_MSG_NUM_MT8173,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
+};
+
 static const struct mtk_i2c_compatible mt6577_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 0,
 	.dcm = 1,
+	.auto_restart = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 1,
 	.dcm = 0,
+	.auto_restart = 0,
+};
+
+static const struct mtk_i2c_compatible mt8173_compat = {
+	.quirks = &mt8173_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+	.auto_restart = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
 	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
 	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
 	{}
 };
-MODULE_DEVICE_TABLE(of, mtk_i2c_match);
+MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
 
 static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
 {
@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
 	return 0;
 }
 
-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
+					int num, int left_num)
 {
 	u16 addr_reg;
+	u16 start_reg;
 	u16 control_reg;
 	dma_addr_t rpaddr = 0;
 	dma_addr_t wpaddr = 0;
@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		control_reg |= I2C_CONTROL_RS;
 	if (i2c->op == I2C_MASTER_WRRD)
 		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	if (left_num >= 1)
+		control_reg |= I2C_CONTROL_RS;
 	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
 
 	/* set start condition */
@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
 
 	/* Clear interrupt status */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
 
 	/* Enable interrupt */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_MASK);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
 
 	/* Set transfer and transaction len */
 	if (i2c->op == I2C_MASTER_WRRD) {
@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
 	} else {
 		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
-		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+		mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
 	}
 
 	/* Prepare buffer data to start transfer */
@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	/* flush before sending start */
 	mb();
 	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
-	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	if (!i2c->dev_comp->auto_restart) {
+		start_reg = I2C_TRANSAC_START;
+	} else {
+		if (left_num >= 1)
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
+					| I2C_RS_MUL_TRIG;
+		else
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
+	}
+	mtk_i2c_writew(start_reg, i2c, OFFSET_START);
 
 	ret = wait_for_completion_timeout(&i2c->msg_complete,
 				i2c->adap.timeout);
 
 	/* Clear interrupt mask */
-	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
 
 	if (i2c->op == I2C_MASTER_WR) {
@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		return -EREMOTEIO;
 	}
 
+	if (i2c->irq_stat & I2C_RS_TRANSFER)
+		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
+				msgs->addr);
+
 	return 0;
 }
 
@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	if (ret)
 		return ret;
 
-	if (msgs->buf == NULL) {
-		dev_dbg(i2c->dev, "data buffer is NULL.\n");
-		ret = -EINVAL;
-		goto err_exit;
-	}
-
-	if (msgs->flags & I2C_M_RD)
-		i2c->op = I2C_MASTER_RD;
-	else
-		i2c->op = I2C_MASTER_WR;
+	while (left_num--) {
+		if (msgs->buf == NULL) {
+			dev_dbg(i2c->dev, "data buffer is NULL.\n");
+			ret = -EINVAL;
+			goto err_exit;
+		}
 
-	if (num > 1) {
-		/* combined two messages into one transaction */
-		i2c->op = I2C_MASTER_WRRD;
-		left_num--;
-	}
+		if (msgs->flags & I2C_M_RD)
+			i2c->op = I2C_MASTER_RD;
+		else
+			i2c->op = I2C_MASTER_WR;
+
+		if (!i2c->dev_comp->auto_restart) {
+			if (num > 1) {
+				/* combined two messages into one transaction */
+				i2c->op = I2C_MASTER_WRRD;
+				left_num--;
+			}
+		}
 
-	/* always use DMA mode. */
-	ret = mtk_i2c_do_transfer(i2c, msgs);
-	if (ret < 0)
-		goto err_exit;
+		/* always use DMA mode. */
+		ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
+		if (ret < 0)
+			goto err_exit;
 
+		msgs++;
+	}
 	/* the return value is number of executed messages */
 	ret = num;
 
@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 	struct mtk_i2c *i2c = dev_id;
 
 	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 
 	complete(&i2c->msg_complete);
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 01:31:06 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 16:31:06 +0800
Subject: [PATCH v6 0/3] ARM: mediatek: Add driver for Mediatek I2C
Message-ID: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>

This series is for Mediatek SoCs I2C controller common bus driver.

Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
New generation SoC like MT8173 fix following limitations:

1. Only support one i2c_msg number. One exception is WRRD (write then read)
mode. WRRD can have two i2c_msg numbers.

2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
mode the Repeat Start will be issued between 2 messages.
In this driver if 2 messages is first write then read, the driver will
combine 2 messages using Write-Read mode so the RS will be issued between
the 2 messages.

3. The max transfer data length is 255 in one message. In WRRD mode, the
max data length of second msg is 31.

MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
bit first, the operation on other registers are still the same.
For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
"mediatek,have-pmic" property in the .dts file of each platform.

This driver is based on 4.1-rc1.

Change in v6:
1. Update binding document not use default clock-frequency as example.
2. Add mtk_i2c_compatible struct and pass hardware capabilities
   through of_device_id
3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
   so just init one time.
4. Correct mtk_i2c_parse_dt don't set default clock bug.

Change in v5:
Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
Add MT8173 I2C driver.

Change in v4:
Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
Remove check transfer size and WRRD combine code. Instead, fill quirk
property and let i2c_check_for_quirks to do the filter.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html

Eddie Huang (1):
  I2C: mediatek: Add driver for MediaTek MT8173 I2C controller

Xudong Chen (2):
  dt-bindings: Add I2C bindings for mt65xx/mt81xx.
  I2C: mediatek: Add driver for MediaTek I2C controller

 .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
 drivers/i2c/busses/Kconfig                         |   9 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

--
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 01:31:08 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 16:31:08 +0800
Subject: [PATCH v6 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
In-Reply-To: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430209869-6631-3-git-send-email-eddie.huang@mediatek.com>

From: Xudong Chen <xudong.chen at mediatek.com>

The mediatek SoCs have I2C controller that handle I2C transfer.
This patch include common I2C bus driver.
This driver is compatible with I2C controller on mt65xx/mt81xx.

Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/i2c/busses/Kconfig      |   9 +
 drivers/i2c/busses/Makefile     |   1 +
 drivers/i2c/busses/i2c-mt65xx.c | 700 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 710 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 2255af2..14c7266 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -620,6 +620,15 @@ config I2C_MPC
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
 
+config I2C_MT65XX
+	tristate "MediaTek I2C adapter"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  This selects the MediaTek(R) Integrated Inter Circuit bus driver
+	  for MT65xx and MT81xx.
+	  If you want to use MediaTek(R) I2C interface, say Y or M here.
+	  If unsure, say N.
+
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
 	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index cdf941d..abbf422 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o
 obj-$(CONFIG_I2C_MESON)		+= i2c-meson.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MT65XX)	+= i2c-mt65xx.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
new file mode 100644
index 0000000..2ecf0d1
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Xudong.chen <xudong.chen at mediatek.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+
+#define I2C_HS_NACKERR			(1 << 2)
+#define I2C_ACKERR			(1 << 1)
+#define I2C_TRANSAC_COMP		(1 << 0)
+#define I2C_TRANSAC_START		(1 << 0)
+#define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
+#define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
+#define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
+#define I2C_TIMING_DATA_READ_MASK	(0x7 << 12)
+#define I2C_DCM_DISABLE			0x0000
+#define I2C_IO_CONFIG_OPEN_DRAIN	0x0003
+#define I2C_IO_CONFIG_PUSH_PULL		0x0000
+#define I2C_SOFT_RST			0x0001
+#define I2C_FIFO_ADDR_CLR		0x0001
+#define I2C_DELAY_LEN			0x0002
+#define I2C_ST_START_CON		0x8001
+#define I2C_FS_START_CON		0x1800
+#define I2C_TIME_CLR_VALUE		0x0000
+#define I2C_TIME_DEFAULT_VALUE		0x0003
+#define I2C_FS_TIME_INIT_VALUE		0x1303
+#define I2C_WRRD_TRANAC_VALUE		0x0002
+#define I2C_RD_TRANAC_VALUE		0x0001
+
+#define I2C_DMA_CON_TX			0x0000
+#define I2C_DMA_CON_RX			0x0001
+#define I2C_DMA_START_EN		0x0001
+#define I2C_DMA_INT_FLAG_NONE		0x0000
+#define I2C_DMA_CLR_FLAG		0x0000
+
+#define I2C_DEFAUT_SPEED		100000	/* hz */
+#define MAX_FS_MODE_SPEED		400000
+#define MAX_HS_MODE_SPEED		3400000
+#define MAX_MSG_NUM_MT6577		1
+#define MAX_DMA_TRANS_SIZE_MT6577	255
+#define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_SAMPLE_CNT_DIV		8
+#define MAX_STEP_CNT_DIV		64
+#define MAX_HS_STEP_CNT_DIV		8
+
+#define I2C_CONTROL_RS                  (0x1 << 1)
+#define I2C_CONTROL_DMA_EN              (0x1 << 2)
+#define I2C_CONTROL_CLK_EXT_EN          (0x1 << 3)
+#define I2C_CONTROL_DIR_CHANGE          (0x1 << 4)
+#define I2C_CONTROL_ACKERR_DET_EN       (0x1 << 5)
+#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_WRAPPER             (0x1 << 0)
+
+#define I2C_DRV_NAME		"mt-i2c"
+
+enum DMA_REGS_OFFSET {
+	OFFSET_INT_FLAG = 0x0,
+	OFFSET_INT_EN = 0x04,
+	OFFSET_EN = 0x08,
+	OFFSET_CON = 0x18,
+	OFFSET_TX_MEM_ADDR = 0x1c,
+	OFFSET_RX_MEM_ADDR = 0x20,
+	OFFSET_TX_LEN = 0x24,
+	OFFSET_RX_LEN = 0x28,
+};
+
+enum i2c_trans_st_rs {
+	I2C_TRANS_STOP = 0,
+	I2C_TRANS_REPEATED_START,
+};
+
+enum mtk_trans_op {
+	I2C_MASTER_WR = 1,
+	I2C_MASTER_RD,
+	I2C_MASTER_WRRD,
+};
+
+enum I2C_REGS_OFFSET {
+	OFFSET_DATA_PORT = 0x0,
+	OFFSET_SLAVE_ADDR = 0x04,
+	OFFSET_INTR_MASK = 0x08,
+	OFFSET_INTR_STAT = 0x0c,
+	OFFSET_CONTROL = 0x10,
+	OFFSET_TRANSFER_LEN = 0x14,
+	OFFSET_TRANSAC_LEN = 0x18,
+	OFFSET_DELAY_LEN = 0x1c,
+	OFFSET_TIMING = 0x20,
+	OFFSET_START = 0x24,
+	OFFSET_EXT_CONF = 0x28,
+	OFFSET_FIFO_STAT = 0x30,
+	OFFSET_FIFO_THRESH = 0x34,
+	OFFSET_FIFO_ADDR_CLR = 0x38,
+	OFFSET_IO_CONFIG = 0x40,
+	OFFSET_RSV_DEBUG = 0x44,
+	OFFSET_HS = 0x48,
+	OFFSET_SOFTRESET = 0x50,
+	OFFSET_DCM_EN = 0x54,
+	OFFSET_PATH_DIR = 0x60,
+	OFFSET_DEBUGSTAT = 0x64,
+	OFFSET_DEBUGCTRL = 0x68,
+	OFFSET_TRANSFER_LEN_AUX = 0x6c,
+};
+
+struct mtk_i2c_data {
+	unsigned int clk_frequency;	/* bus speed in Hz */
+	unsigned int flags;
+	unsigned int clk_src_div;
+};
+
+struct mtk_i2c_compatible {
+	const struct i2c_adapter_quirks *quirks;
+	unsigned char pmic_i2c;
+	unsigned char dcm;
+};
+
+struct mtk_i2c {
+	struct i2c_adapter adap;	/* i2c host adapter */
+	struct device *dev;
+	struct completion msg_complete;
+
+	/* set in i2c probe */
+	void __iomem *base;		/* i2c base addr */
+	void __iomem *pdmabase;		/* dma base address*/
+	struct clk *clk_main;		/* main clock for i2c bus */
+	struct clk *clk_dma;		/* DMA clock for i2c via DMA */
+	struct clk *clk_pmic;		/* PMIC clock for i2c from PMIC */
+	bool have_pmic;			/* can use i2c pins from PMIC */
+	bool use_push_pull;		/* IO config push-pull mode */
+
+	u16 irq_stat;			/* interrupt status */
+	unsigned int speed_hz;		/* The speed in transfer */
+	enum mtk_trans_op op;
+	u16 timing_reg;
+	u16 high_speed_reg;
+	const struct mtk_i2c_compatible *dev_comp;
+};
+
+static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
+	.max_num_msgs = MAX_MSG_NUM_MT6577,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+};
+
+static const struct mtk_i2c_compatible mt6577_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+};
+
+static const struct mtk_i2c_compatible mt6589_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 1,
+	.dcm = 0,
+};
+
+static const struct of_device_id mtk_i2c_of_match[] = {
+	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_i2c_match);
+
+static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writew(value, i2c->base + offset);
+}
+
+static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
+{
+	return readw(i2c->base + offset);
+}
+
+static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writel(value, i2c->pdmabase + offset);
+}
+
+static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
+{
+	int ret;
+
+	ret = clk_prepare_enable(i2c->clk_dma);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(i2c->clk_main);
+	if (ret)
+		goto err_main;
+
+	if (i2c->have_pmic) {
+		ret = clk_prepare_enable(i2c->clk_pmic);
+		if (ret)
+			goto err_pmic;
+	}
+	return 0;
+
+err_pmic:
+	clk_disable_unprepare(i2c->clk_main);
+err_main:
+	clk_disable_unprepare(i2c->clk_dma);
+
+	return ret;
+}
+
+static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+{
+	if (i2c->have_pmic)
+		clk_disable_unprepare(i2c->clk_pmic);
+
+	clk_disable_unprepare(i2c->clk_main);
+	clk_disable_unprepare(i2c->clk_dma);
+}
+
+static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
+{
+	u16 control_reg;
+
+	mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
+	/* Set ioconfig */
+	if (i2c->use_push_pull)
+		mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
+	else
+		mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
+
+	if (i2c->dev_comp->dcm)
+		mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
+
+	mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
+	mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
+
+	/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
+	if (i2c->have_pmic)
+		mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
+
+	control_reg = I2C_CONTROL_ACKERR_DET_EN |
+		I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+	mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
+}
+
+/* calculate i2c port speed */
+static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+{
+	unsigned int khz;
+	unsigned int step_cnt;
+	unsigned int sample_cnt;
+	unsigned int sclk;
+	unsigned int hclk;
+	unsigned int max_step_cnt;
+	unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
+	unsigned int step_div;
+	unsigned int min_div;
+	unsigned int best_mul;
+	unsigned int cnt_mul;
+
+	if (i2c->speed_hz > MAX_HS_MODE_SPEED)
+		return -EINVAL;
+	else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
+		max_step_cnt = MAX_HS_STEP_CNT_DIV;
+	else
+		max_step_cnt = MAX_STEP_CNT_DIV;
+
+	step_div = max_step_cnt;
+	/* Find the best combination */
+	khz = i2c->speed_hz / 1000;
+	hclk = clk_src_in_hz / 1000;
+	min_div = ((hclk >> 1) + khz - 1) / khz;
+	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
+
+	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+		step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
+		cnt_mul = step_cnt * sample_cnt;
+		if (step_cnt > max_step_cnt)
+			continue;
+
+		if (cnt_mul < best_mul) {
+			best_mul = cnt_mul;
+			sample_div = sample_cnt;
+			step_div = step_cnt;
+			if (best_mul == min_div)
+				break;
+		}
+	}
+
+	sample_cnt = sample_div;
+	step_cnt = step_div;
+	sclk = hclk / (2 * sample_cnt * step_cnt);
+	if (sclk > khz) {
+		dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
+			(i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
+			(long int)khz);
+		return -ENOTSUPP;
+	}
+
+	step_cnt--;
+	sample_cnt--;
+
+	if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
+		/* Set the hign speed mode register */
+		i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
+		i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
+			(step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
+	} else {
+		i2c->timing_reg =
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
+			(step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
+		/* Disable the high speed transaction */
+		i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+{
+	u16 addr_reg;
+	u16 control_reg;
+	dma_addr_t rpaddr = 0;
+	dma_addr_t wpaddr = 0;
+	int ret;
+
+	i2c->irq_stat = 0;
+
+	reinit_completion(&i2c->msg_complete);
+
+	control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
+			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
+	if (i2c->speed_hz > 400000)
+		control_reg |= I2C_CONTROL_RS;
+	if (i2c->op == I2C_MASTER_WRRD)
+		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+
+	/* set start condition */
+	if (i2c->speed_hz <= 100000)
+		mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
+	else
+		mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
+
+	addr_reg = msgs->addr << 1;
+	if (i2c->op == I2C_MASTER_RD)
+		addr_reg |= 0x1;
+	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+
+	/* Clear interrupt status */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+
+	/* Enable interrupt */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_MASK);
+
+	/* Set transfer and transaction len */
+	if (i2c->op == I2C_MASTER_WRRD) {
+		mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
+			i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	} else {
+		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	}
+
+	/* Prepare buffer data to start transfer */
+	if (i2c->op == I2C_MASTER_RD) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
+		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
+	} else if (i2c->op == I2C_MASTER_WR) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+	} else {
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
+						(msgs + 1)->len,
+						DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
+			dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+						msgs->len, DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+		mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
+	}
+
+	/* flush before sending start */
+	mb();
+	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	ret = wait_for_completion_timeout(&i2c->msg_complete,
+				i2c->adap.timeout);
+
+	/* Clear interrupt mask */
+	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+
+	if (i2c->op == I2C_MASTER_WR) {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+					msgs->len, DMA_TO_DEVICE);
+	} else if (i2c->op == I2C_MASTER_RD) {
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr,
+					msgs->len, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
+					DMA_TO_DEVICE);
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
+					DMA_FROM_DEVICE);
+	}
+
+	if (ret == 0) {
+		dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -ETIMEDOUT;
+	}
+
+	completion_done(&i2c->msg_complete);
+
+	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
+		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_transfer(struct i2c_adapter *adap,
+	struct i2c_msg msgs[], int num)
+{
+	int ret;
+	int left_num = num;
+	struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret)
+		return ret;
+
+	if (msgs->buf == NULL) {
+		dev_dbg(i2c->dev, "data buffer is NULL.\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	if (msgs->flags & I2C_M_RD)
+		i2c->op = I2C_MASTER_RD;
+	else
+		i2c->op = I2C_MASTER_WR;
+
+	if (num > 1) {
+		/* combined two messages into one transaction */
+		i2c->op = I2C_MASTER_WRRD;
+		left_num--;
+	}
+
+	/* always use DMA mode. */
+	ret = mtk_i2c_do_transfer(i2c, msgs);
+	if (ret < 0)
+		goto err_exit;
+
+	/* the return value is number of executed messages */
+	ret = num;
+
+err_exit:
+	mtk_i2c_clock_disable(i2c);
+	return ret;
+}
+
+static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+{
+	struct mtk_i2c *i2c = dev_id;
+
+	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+
+	complete(&i2c->msg_complete);
+
+	return IRQ_HANDLED;
+}
+
+static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mtk_i2c_algorithm = {
+	.master_xfer = mtk_i2c_transfer,
+	.functionality = mtk_i2c_functionality,
+};
+
+static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
+	unsigned int *clk_src_div)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
+	if (ret < 0)
+		i2c->speed_hz = I2C_DEFAUT_SPEED;
+
+	ret = of_property_read_u32(np, "clock-div", clk_src_div);
+	if (ret < 0)
+		return ret;
+
+	if (*clk_src_div == 0)
+		return -EINVAL;
+
+	i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
+	i2c->use_push_pull =
+		of_property_read_bool(np, "mediatek,use-push-pull");
+
+	return 0;
+}
+
+static int mtk_i2c_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	int ret = 0;
+	struct mtk_i2c *i2c;
+	struct clk *clk;
+	unsigned int clk_src_in_hz;
+	unsigned int clk_src_div;
+	struct resource *res;
+	int irq;
+
+	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+	if (i2c == NULL)
+		return -ENOMEM;
+
+	ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
+	if (ret)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->base))
+		return PTR_ERR(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->pdmabase))
+		return PTR_ERR(i2c->pdmabase);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq;
+
+	init_completion(&i2c->msg_complete);
+
+	of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	i2c->dev_comp = of_id->data;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+	i2c->dev = &i2c->adap.dev;
+	i2c->adap.dev.parent = &pdev->dev;
+	i2c->adap.owner = THIS_MODULE;
+	i2c->adap.algo = &mtk_i2c_algorithm;
+	i2c->adap.quirks = i2c->dev_comp->quirks;
+	i2c->adap.timeout = 2 * HZ;
+	i2c->adap.retries = 1;
+
+	if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
+		return -EINVAL;
+
+	i2c->clk_main = devm_clk_get(&pdev->dev, "main");
+	if (IS_ERR(i2c->clk_main)) {
+		dev_err(&pdev->dev, "cannot get main clock\n");
+		return PTR_ERR(i2c->clk_main);
+	}
+
+	i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
+	if (IS_ERR(i2c->clk_dma)) {
+		dev_err(&pdev->dev, "cannot get dma clock\n");
+		return PTR_ERR(i2c->clk_dma);
+	}
+
+	clk = i2c->clk_main;
+	if (i2c->have_pmic) {
+		i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
+		if (IS_ERR(i2c->clk_pmic)) {
+			dev_err(&pdev->dev, "cannot get pmic clock\n");
+			return PTR_ERR(i2c->clk_pmic);
+		}
+		clk = i2c->clk_pmic;
+	}
+	clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
+
+	dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
+		i2c->clk_main, clk_src_in_hz);
+	strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+
+	ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set the speed.\n");
+		return -EINVAL;
+	}
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "clock enable failed!\n");
+		return ret;
+	}
+	mtk_i2c_init_hw(i2c);
+	mtk_i2c_clock_disable(i2c);
+
+	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+		IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Request I2C IRQ %d fail\n", irq);
+		return ret;
+	}
+
+	i2c_set_adapdata(&i2c->adap, i2c);
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, i2c);
+
+	return 0;
+}
+
+static int mtk_i2c_remove(struct platform_device *pdev)
+{
+	struct mtk_i2c *i2c = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c->adap);
+
+	return 0;
+}
+
+static struct platform_driver mtk_i2c_driver = {
+	.probe = mtk_i2c_probe,
+	.remove = mtk_i2c_remove,
+	.driver = {
+		.name = I2C_DRV_NAME,
+		.of_match_table = of_match_ptr(mtk_i2c_of_match),
+	},
+};
+
+module_platform_driver(mtk_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
+MODULE_AUTHOR("Xudong Chen <xudong.chen at mediatek.com>");
-- 
1.8.1.1.dirty



From mkl at pengutronix.de  Tue Apr 28 01:36:17 2015
From: mkl at pengutronix.de (Marc Kleine-Budde)
Date: Tue, 28 Apr 2015 10:36:17 +0200
Subject: [PATCH v6 3/3] I2C: mediatek: Add driver for MediaTek
 MT8173 I2C controller
In-Reply-To: <1430209869-6631-4-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
 <1430209869-6631-4-git-send-email-eddie.huang@mediatek.com>
Message-ID: <553F4681.7040404@pengutronix.de>

On 04/28/2015 10:31 AM, Eddie Huang wrote:
> Add mediatek MT8173 I2C controller driver. Compare to I2C controller
> of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
> also increase message size to 64kb.
> 
> Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
> Signed-off-by: Liguo Zhang <liguo.zhang at mediatek.com>
> Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 106 +++++++++++++++++++++++++++++-----------
>  1 file changed, 77 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 2ecf0d1..c501421 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
[...]

>  static const struct of_device_id mtk_i2c_of_match[] = {
>  	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
>  	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> +	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
>  	{}
>  };
> -MODULE_DEVICE_TABLE(of, mtk_i2c_match);
> +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);

This should go into the previous patch, as 2/3 will probably not compile
without this change.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150428/feac6525/attachment.sig>

From eddie.huang at mediatek.com  Tue Apr 28 01:44:48 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 16:44:48 +0800
Subject: [PATCH v6 3/3] I2C: mediatek: Add driver for MediaTek MT8173
 I2C controller
In-Reply-To: <553F4681.7040404@pengutronix.de>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
 <1430209869-6631-4-git-send-email-eddie.huang@mediatek.com>
 <553F4681.7040404@pengutronix.de>
Message-ID: <1430210688.26793.1.camel@mtksdaap41>

Hi Marc,

On Tue, 2015-04-28 at 10:36 +0200, Marc Kleine-Budde wrote:
> On 04/28/2015 10:31 AM, Eddie Huang wrote:
> > Add mediatek MT8173 I2C controller driver. Compare to I2C controller
> > of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
> > also increase message size to 64kb.
> > 
> > Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
> > Signed-off-by: Liguo Zhang <liguo.zhang at mediatek.com>
> > Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c | 106 +++++++++++++++++++++++++++++-----------
> >  1 file changed, 77 insertions(+), 29 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> > index 2ecf0d1..c501421 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> [...]
> 
> >  static const struct of_device_id mtk_i2c_of_match[] = {
> >  	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> >  	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> > +	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
> >  	{}
> >  };
> > -MODULE_DEVICE_TABLE(of, mtk_i2c_match);
> > +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
> 
> This should go into the previous patch, as 2/3 will probably not compile
> without this change.
> 
That's right, my mistake, should be in 2/3. 

Eddie





From s.hauer at pengutronix.de  Tue Apr 28 01:25:56 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:56 +0200
Subject: [PATCH 06/13] thermal: Add comment explaining test for critical
 temperature
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-7-git-send-email-s.hauer@pengutronix.de>

The code testing if a temperature should be emulated or not is
not obvious. Add a comment explaining why this test is done.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4633964..ffe09186 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -435,6 +435,11 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 			}
 		}
 
+		/*
+		 * Only allow emulating a temperature when the real temperature
+		 * is below the critical temperature so that the emulation code
+		 * cannot hide critical conditions.
+		 */
 		if (!ret && *temp < crit_temp)
 			*temp = tz->emul_temperature;
 	}
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:55 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:55 +0200
Subject: [PATCH 05/13] thermal: Use IS_ENABLED instead of #ifdef
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-6-git-send-email-s.hauer@pengutronix.de>

Use IS_ENABLED(CONFIG_THERMAL_EMULATION) to make the code more readable
and to get rid of the addtional #ifdef around the variable definitions
in thermal_zone_get_temp().

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 43 ++++++++++++++++++------------------------
 1 file changed, 18 insertions(+), 25 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index ad1d3c9..4633964 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -414,11 +414,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 {
 	int ret = -EINVAL;
-#ifdef CONFIG_THERMAL_EMULATION
 	int count;
 	int crit_temp = INT_MAX;
 	enum thermal_trip_type type;
-#endif
 
 	if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
 		goto exit;
@@ -426,25 +424,21 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
 	mutex_lock(&tz->lock);
 
 	ret = tz->ops->get_temp(tz, temp);
-#ifdef CONFIG_THERMAL_EMULATION
-	if (!tz->emul_temperature)
-		goto skip_emul;
-
-	for (count = 0; count < tz->trips; count++) {
-		ret = tz->ops->get_trip_type(tz, count, &type);
-		if (!ret && type == THERMAL_TRIP_CRITICAL) {
-			ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
-			break;
+
+	if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
+		for (count = 0; count < tz->trips; count++) {
+			ret = tz->ops->get_trip_type(tz, count, &type);
+			if (!ret && type == THERMAL_TRIP_CRITICAL) {
+				ret = tz->ops->get_trip_temp(tz, count,
+						&crit_temp);
+				break;
+			}
 		}
-	}
 
-	if (ret)
-		goto skip_emul;
+		if (!ret && *temp < crit_temp)
+			*temp = tz->emul_temperature;
+	}
 
-	if (*temp < crit_temp)
-		*temp = tz->emul_temperature;
-skip_emul:
-#endif
 	mutex_unlock(&tz->lock);
 exit:
 	return ret;
@@ -780,7 +774,6 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
 	return sprintf(buf, "%s\n", tz->governor->name);
 }
 
-#ifdef CONFIG_THERMAL_EMULATION
 static ssize_t
 emul_temp_store(struct device *dev, struct device_attribute *attr,
 		     const char *buf, size_t count)
@@ -806,7 +799,6 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
 	return ret ? ret : count;
 }
 static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
-#endif/*CONFIG_THERMAL_EMULATION*/
 
 static DEVICE_ATTR(type, 0444, type_show, NULL);
 static DEVICE_ATTR(temp, 0444, temp_show, NULL);
@@ -1536,11 +1528,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 			goto unregister;
 	}
 
-#ifdef CONFIG_THERMAL_EMULATION
-	result = device_create_file(&tz->device, &dev_attr_emul_temp);
-	if (result)
-		goto unregister;
-#endif
+	if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
+		result = device_create_file(&tz->device, &dev_attr_emul_temp);
+		if (result)
+			goto unregister;
+	}
+
 	/* Create policy attribute */
 	result = device_create_file(&tz->device, &dev_attr_policy);
 	if (result)
-- 
2.1.4



From s.hauer at pengutronix.de  Tue Apr 28 01:25:57 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 10:25:57 +0200
Subject: [PATCH 07/13] thermal: inline only once used function
In-Reply-To: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
References: <1430209563-647-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430209563-647-8-git-send-email-s.hauer@pengutronix.de>

Inline update_temperature into its only caller to make the code
more readable.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/thermal/thermal_core.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index ffe09186..81ebc24 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -450,9 +450,12 @@ exit:
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
 
-static void update_temperature(struct thermal_zone_device *tz)
+void thermal_zone_device_update(struct thermal_zone_device *tz)
 {
-	int temp, ret;
+	int temp, ret, count;
+
+	if (!tz->ops->get_temp)
+		return;
 
 	ret = thermal_zone_get_temp(tz, &temp);
 	if (ret) {
@@ -471,16 +474,6 @@ static void update_temperature(struct thermal_zone_device *tz)
 	trace_thermal_temperature(tz);
 	dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
 				tz->last_temperature, tz->temperature);
-}
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
-{
-	int count;
-
-	if (!tz->ops->get_temp)
-		return;
-
-	update_temperature(tz);
 
 	for (count = 0; count < tz->trips; count++)
 		handle_thermal_trip(tz, count);
-- 
2.1.4



From yingjoe.chen at mediatek.com  Tue Apr 28 02:23:57 2015
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Tue, 28 Apr 2015 17:23:57 +0800
Subject: [PATCH 2/2] arm64: dts: mt8173: Fixup pinctrl nodes
In-Reply-To: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>
References: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>
Message-ID: <1430213037-23831-2-git-send-email-yingjoe.chen@mediatek.com>

The 8173 pinctrl node doesn't follow dts convention. Fix them.
Also add a comment to explain pinctrl register usage to make it
more clear.

Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 8346c0f..e4a30cd 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -128,6 +128,7 @@
 		compatible = "simple-bus";
 		ranges;
 
+		/* Provide regmap for pinctrl driver */
 		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
 			compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon";
 			reg = <0 0x10005000 0 0x1000>;
@@ -159,9 +160,13 @@
 			#reset-cells = <1>;
 		};
 
-		pio: pinctrl at 0x10005000 {
+		/*
+		 * Pinctrl access register at 0x10005000 through regmap.
+		 * Register 0x1000b000 is used by EINT.
+		 */
+		pio: pinctrl at 10005000 {
 			compatible = "mediatek,mt8173-pinctrl";
-			reg = <0 0x1000B000 0 0x1000>;
+			reg = <0 0x1000b000 0 0x1000>;
 			mediatek,pctl-regmap = <&syscfg_pctl_a>;
 			pins-are-numbered;
 			gpio-controller;
@@ -169,8 +174,8 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
-						<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
-						<GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+				     <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		sysirq: intpol-controller at 10200620 {
-- 
1.8.1.1.dirty



From yingjoe.chen at mediatek.com  Tue Apr 28 02:23:56 2015
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Tue, 28 Apr 2015 17:23:56 +0800
Subject: [PATCH 1/2] ARM: dts: mt8135: Add pinctrl/GPIO/EINT node for mt8135.
Message-ID: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>

From: Hongzhou Yang <hongzhou.yang at mediatek.com>


Matthias,

Since mt8135 pinctrl node patch is not in v4.1-rc1, I'd like to make some minor
change to follow dts convention.

Let me know what you think.
Thanks.

Joe.C

---8<--------------------------------------------------------------------
Add pinctrl,GPIO and EINT node to mt8135.dtsi.

Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
Signed-off-by: Hongzhou Yang <hongzhou.yang at mediatek.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/boot/dts/mt8135-pinfunc.h | 1302 ++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/mt8135.dtsi      |   31 +
 2 files changed, 1333 insertions(+)
 create mode 100644 arch/arm/boot/dts/mt8135-pinfunc.h

diff --git a/arch/arm/boot/dts/mt8135-pinfunc.h b/arch/arm/boot/dts/mt8135-pinfunc.h
new file mode 100644
index 0000000..5a60987
--- /dev/null
+++ b/arch/arm/boot/dts/mt8135-pinfunc.h
@@ -0,0 +1,1302 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang at mediatek.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.
+ */
+
+#ifndef __DTS_MT8135_PINFUNC_H
+#define __DTS_MT8135_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(0) | 1)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_EINT49 (MTK_PIN_NO(0) | 2)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_I2SOUT_DAT (MTK_PIN_NO(0) | 3)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_DAC_DAT_OUT (MTK_PIN_NO(0) | 4)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_PCM1_DO (MTK_PIN_NO(0) | 5)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_SPI1_MO (MTK_PIN_NO(0) | 6)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_NALE (MTK_PIN_NO(0) | 7)
+
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(1) | 1)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_EINT48 (MTK_PIN_NO(1) | 2)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_I2SIN_WS (MTK_PIN_NO(1) | 3)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_DAC_WS (MTK_PIN_NO(1) | 4)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_PCM1_WS (MTK_PIN_NO(1) | 5)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_SPI1_CSN (MTK_PIN_NO(1) | 6)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_NCLE (MTK_PIN_NO(1) | 7)
+
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(2) | 1)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_EINT47 (MTK_PIN_NO(2) | 2)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_I2SIN_CK (MTK_PIN_NO(2) | 3)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_DAC_CK (MTK_PIN_NO(2) | 4)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_PCM1_CK (MTK_PIN_NO(2) | 5)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_SPI1_CLK (MTK_PIN_NO(2) | 6)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(2) | 7)
+
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(3) | 1)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_EINT46 (MTK_PIN_NO(3) | 2)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_A_FUNC_CK (MTK_PIN_NO(3) | 3)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_LSCE1B_2X (MTK_PIN_NO(3) | 6)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_NLD5 (MTK_PIN_NO(3) | 7)
+
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(4) | 1)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_EINT41 (MTK_PIN_NO(4) | 2)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_A_FUNC_DOUT_0 (MTK_PIN_NO(4) | 3)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_USB_TEST_IO_0 (MTK_PIN_NO(4) | 5)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_LRSTB_2X (MTK_PIN_NO(4) | 6)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_NRNB (MTK_PIN_NO(4) | 7)
+
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(5) | 1)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_EINT40 (MTK_PIN_NO(5) | 2)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_A_FUNC_DOUT_1 (MTK_PIN_NO(5) | 3)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_USB_TEST_IO_1 (MTK_PIN_NO(5) | 5)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_LPTE (MTK_PIN_NO(5) | 6)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_NREB (MTK_PIN_NO(5) | 7)
+
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(6) | 1)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_EINT45 (MTK_PIN_NO(6) | 2)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_A_FUNC_DOUT_2 (MTK_PIN_NO(6) | 3)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_USB_TEST_IO_2 (MTK_PIN_NO(6) | 5)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_LSCE0B_2X (MTK_PIN_NO(6) | 6)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_NLD7 (MTK_PIN_NO(6) | 7)
+
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(7) | 1)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_EINT44 (MTK_PIN_NO(7) | 2)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_A_FUNC_DOUT_3 (MTK_PIN_NO(7) | 3)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_USB_TEST_IO_3 (MTK_PIN_NO(7) | 5)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_LSA0_2X (MTK_PIN_NO(7) | 6)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_NLD14 (MTK_PIN_NO(7) | 7)
+
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(8) | 1)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_EINT43 (MTK_PIN_NO(8) | 2)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_USB_TEST_IO_4 (MTK_PIN_NO(8) | 5)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_LSCK_2X (MTK_PIN_NO(8) | 6)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_NLD11 (MTK_PIN_NO(8) | 7)
+
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(9) | 1)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_EINT42 (MTK_PIN_NO(9) | 2)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_USB_TEST_IO_5 (MTK_PIN_NO(9) | 5)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_LSDA_2X (MTK_PIN_NO(9) | 6)
+
+#define MT8135_PIN_10_NCEB0__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT8135_PIN_10_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(10) | 1)
+#define MT8135_PIN_10_NCEB0__FUNC_EINT139 (MTK_PIN_NO(10) | 2)
+#define MT8135_PIN_10_NCEB0__FUNC_TESTA_OUT4 (MTK_PIN_NO(10) | 7)
+
+#define MT8135_PIN_11_NCEB1__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT8135_PIN_11_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(11) | 1)
+#define MT8135_PIN_11_NCEB1__FUNC_EINT140 (MTK_PIN_NO(11) | 2)
+#define MT8135_PIN_11_NCEB1__FUNC_USB_DRVVBUS (MTK_PIN_NO(11) | 6)
+#define MT8135_PIN_11_NCEB1__FUNC_TESTA_OUT5 (MTK_PIN_NO(11) | 7)
+
+#define MT8135_PIN_12_NRNB__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT8135_PIN_12_NRNB__FUNC_NRNB (MTK_PIN_NO(12) | 1)
+#define MT8135_PIN_12_NRNB__FUNC_EINT141 (MTK_PIN_NO(12) | 2)
+#define MT8135_PIN_12_NRNB__FUNC_A_FUNC_DOUT_4 (MTK_PIN_NO(12) | 3)
+#define MT8135_PIN_12_NRNB__FUNC_TESTA_OUT6 (MTK_PIN_NO(12) | 7)
+
+#define MT8135_PIN_13_NCLE__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT8135_PIN_13_NCLE__FUNC_NCLE (MTK_PIN_NO(13) | 1)
+#define MT8135_PIN_13_NCLE__FUNC_EINT142 (MTK_PIN_NO(13) | 2)
+#define MT8135_PIN_13_NCLE__FUNC_A_FUNC_DOUT_5 (MTK_PIN_NO(13) | 3)
+#define MT8135_PIN_13_NCLE__FUNC_CM2PDN_1X (MTK_PIN_NO(13) | 4)
+#define MT8135_PIN_13_NCLE__FUNC_NALE (MTK_PIN_NO(13) | 6)
+#define MT8135_PIN_13_NCLE__FUNC_TESTA_OUT7 (MTK_PIN_NO(13) | 7)
+
+#define MT8135_PIN_14_NALE__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT8135_PIN_14_NALE__FUNC_NALE (MTK_PIN_NO(14) | 1)
+#define MT8135_PIN_14_NALE__FUNC_EINT143 (MTK_PIN_NO(14) | 2)
+#define MT8135_PIN_14_NALE__FUNC_A_FUNC_DOUT_6 (MTK_PIN_NO(14) | 3)
+#define MT8135_PIN_14_NALE__FUNC_CM2MCLK_1X (MTK_PIN_NO(14) | 4)
+#define MT8135_PIN_14_NALE__FUNC_IRDA_RXD (MTK_PIN_NO(14) | 5)
+#define MT8135_PIN_14_NALE__FUNC_NCLE (MTK_PIN_NO(14) | 6)
+#define MT8135_PIN_14_NALE__FUNC_TESTA_OUT8 (MTK_PIN_NO(14) | 7)
+
+#define MT8135_PIN_15_NREB__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT8135_PIN_15_NREB__FUNC_NREB (MTK_PIN_NO(15) | 1)
+#define MT8135_PIN_15_NREB__FUNC_EINT144 (MTK_PIN_NO(15) | 2)
+#define MT8135_PIN_15_NREB__FUNC_A_FUNC_DOUT_7 (MTK_PIN_NO(15) | 3)
+#define MT8135_PIN_15_NREB__FUNC_CM2RST_1X (MTK_PIN_NO(15) | 4)
+#define MT8135_PIN_15_NREB__FUNC_IRDA_TXD (MTK_PIN_NO(15) | 5)
+#define MT8135_PIN_15_NREB__FUNC_TESTA_OUT9 (MTK_PIN_NO(15) | 7)
+
+#define MT8135_PIN_16_NWEB__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define MT8135_PIN_16_NWEB__FUNC_NWEB (MTK_PIN_NO(16) | 1)
+#define MT8135_PIN_16_NWEB__FUNC_EINT145 (MTK_PIN_NO(16) | 2)
+#define MT8135_PIN_16_NWEB__FUNC_A_FUNC_DIN_0 (MTK_PIN_NO(16) | 3)
+#define MT8135_PIN_16_NWEB__FUNC_CM2PCLK_1X (MTK_PIN_NO(16) | 4)
+#define MT8135_PIN_16_NWEB__FUNC_IRDA_PDN (MTK_PIN_NO(16) | 5)
+#define MT8135_PIN_16_NWEB__FUNC_TESTA_OUT10 (MTK_PIN_NO(16) | 7)
+
+#define MT8135_PIN_17_NLD0__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define MT8135_PIN_17_NLD0__FUNC_NLD0 (MTK_PIN_NO(17) | 1)
+#define MT8135_PIN_17_NLD0__FUNC_EINT146 (MTK_PIN_NO(17) | 2)
+#define MT8135_PIN_17_NLD0__FUNC_A_FUNC_DIN_1 (MTK_PIN_NO(17) | 3)
+#define MT8135_PIN_17_NLD0__FUNC_CM2DAT_1X_0 (MTK_PIN_NO(17) | 4)
+#define MT8135_PIN_17_NLD0__FUNC_I2SIN_CK (MTK_PIN_NO(17) | 5)
+#define MT8135_PIN_17_NLD0__FUNC_DAC_CK (MTK_PIN_NO(17) | 6)
+#define MT8135_PIN_17_NLD0__FUNC_TESTA_OUT11 (MTK_PIN_NO(17) | 7)
+
+#define MT8135_PIN_18_NLD1__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT8135_PIN_18_NLD1__FUNC_NLD1 (MTK_PIN_NO(18) | 1)
+#define MT8135_PIN_18_NLD1__FUNC_EINT147 (MTK_PIN_NO(18) | 2)
+#define MT8135_PIN_18_NLD1__FUNC_A_FUNC_DIN_2 (MTK_PIN_NO(18) | 3)
+#define MT8135_PIN_18_NLD1__FUNC_CM2DAT_1X_1 (MTK_PIN_NO(18) | 4)
+#define MT8135_PIN_18_NLD1__FUNC_I2SIN_WS (MTK_PIN_NO(18) | 5)
+#define MT8135_PIN_18_NLD1__FUNC_DAC_WS (MTK_PIN_NO(18) | 6)
+#define MT8135_PIN_18_NLD1__FUNC_TESTA_OUT12 (MTK_PIN_NO(18) | 7)
+
+#define MT8135_PIN_19_NLD2__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT8135_PIN_19_NLD2__FUNC_NLD2 (MTK_PIN_NO(19) | 1)
+#define MT8135_PIN_19_NLD2__FUNC_EINT148 (MTK_PIN_NO(19) | 2)
+#define MT8135_PIN_19_NLD2__FUNC_A_FUNC_DIN_3 (MTK_PIN_NO(19) | 3)
+#define MT8135_PIN_19_NLD2__FUNC_CM2DAT_1X_2 (MTK_PIN_NO(19) | 4)
+#define MT8135_PIN_19_NLD2__FUNC_I2SOUT_DAT (MTK_PIN_NO(19) | 5)
+#define MT8135_PIN_19_NLD2__FUNC_DAC_DAT_OUT (MTK_PIN_NO(19) | 6)
+#define MT8135_PIN_19_NLD2__FUNC_TESTA_OUT13 (MTK_PIN_NO(19) | 7)
+
+#define MT8135_PIN_20_NLD3__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT8135_PIN_20_NLD3__FUNC_NLD3 (MTK_PIN_NO(20) | 1)
+#define MT8135_PIN_20_NLD3__FUNC_EINT149 (MTK_PIN_NO(20) | 2)
+#define MT8135_PIN_20_NLD3__FUNC_A_FUNC_DIN_4 (MTK_PIN_NO(20) | 3)
+#define MT8135_PIN_20_NLD3__FUNC_CM2DAT_1X_3 (MTK_PIN_NO(20) | 4)
+#define MT8135_PIN_20_NLD3__FUNC_TESTA_OUT14 (MTK_PIN_NO(20) | 7)
+
+#define MT8135_PIN_21_NLD4__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT8135_PIN_21_NLD4__FUNC_NLD4 (MTK_PIN_NO(21) | 1)
+#define MT8135_PIN_21_NLD4__FUNC_EINT150 (MTK_PIN_NO(21) | 2)
+#define MT8135_PIN_21_NLD4__FUNC_A_FUNC_DIN_5 (MTK_PIN_NO(21) | 3)
+#define MT8135_PIN_21_NLD4__FUNC_CM2DAT_1X_4 (MTK_PIN_NO(21) | 4)
+#define MT8135_PIN_21_NLD4__FUNC_TESTA_OUT15 (MTK_PIN_NO(21) | 7)
+
+#define MT8135_PIN_22_NLD5__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT8135_PIN_22_NLD5__FUNC_NLD5 (MTK_PIN_NO(22) | 1)
+#define MT8135_PIN_22_NLD5__FUNC_EINT151 (MTK_PIN_NO(22) | 2)
+#define MT8135_PIN_22_NLD5__FUNC_A_FUNC_DIN_6 (MTK_PIN_NO(22) | 3)
+#define MT8135_PIN_22_NLD5__FUNC_CM2DAT_1X_5 (MTK_PIN_NO(22) | 4)
+#define MT8135_PIN_22_NLD5__FUNC_TESTA_OUT16 (MTK_PIN_NO(22) | 7)
+
+#define MT8135_PIN_23_NLD6__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT8135_PIN_23_NLD6__FUNC_NLD6 (MTK_PIN_NO(23) | 1)
+#define MT8135_PIN_23_NLD6__FUNC_EINT152 (MTK_PIN_NO(23) | 2)
+#define MT8135_PIN_23_NLD6__FUNC_A_FUNC_DIN_7 (MTK_PIN_NO(23) | 3)
+#define MT8135_PIN_23_NLD6__FUNC_CM2DAT_1X_6 (MTK_PIN_NO(23) | 4)
+#define MT8135_PIN_23_NLD6__FUNC_TESTA_OUT17 (MTK_PIN_NO(23) | 7)
+
+#define MT8135_PIN_24_NLD7__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT8135_PIN_24_NLD7__FUNC_NLD7 (MTK_PIN_NO(24) | 1)
+#define MT8135_PIN_24_NLD7__FUNC_EINT153 (MTK_PIN_NO(24) | 2)
+#define MT8135_PIN_24_NLD7__FUNC_A_FUNC_DIN_8 (MTK_PIN_NO(24) | 3)
+#define MT8135_PIN_24_NLD7__FUNC_CM2DAT_1X_7 (MTK_PIN_NO(24) | 4)
+#define MT8135_PIN_24_NLD7__FUNC_TESTA_OUT18 (MTK_PIN_NO(24) | 7)
+
+#define MT8135_PIN_25_NLD8__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT8135_PIN_25_NLD8__FUNC_NLD8 (MTK_PIN_NO(25) | 1)
+#define MT8135_PIN_25_NLD8__FUNC_EINT154 (MTK_PIN_NO(25) | 2)
+#define MT8135_PIN_25_NLD8__FUNC_CM2DAT_1X_8 (MTK_PIN_NO(25) | 4)
+
+#define MT8135_PIN_26_NLD9__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT8135_PIN_26_NLD9__FUNC_NLD9 (MTK_PIN_NO(26) | 1)
+#define MT8135_PIN_26_NLD9__FUNC_EINT155 (MTK_PIN_NO(26) | 2)
+#define MT8135_PIN_26_NLD9__FUNC_CM2DAT_1X_9 (MTK_PIN_NO(26) | 4)
+#define MT8135_PIN_26_NLD9__FUNC_PWM1 (MTK_PIN_NO(26) | 5)
+
+#define MT8135_PIN_27_NLD10__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT8135_PIN_27_NLD10__FUNC_NLD10 (MTK_PIN_NO(27) | 1)
+#define MT8135_PIN_27_NLD10__FUNC_EINT156 (MTK_PIN_NO(27) | 2)
+#define MT8135_PIN_27_NLD10__FUNC_CM2VSYNC_1X (MTK_PIN_NO(27) | 4)
+#define MT8135_PIN_27_NLD10__FUNC_PWM2 (MTK_PIN_NO(27) | 5)
+
+#define MT8135_PIN_28_NLD11__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT8135_PIN_28_NLD11__FUNC_NLD11 (MTK_PIN_NO(28) | 1)
+#define MT8135_PIN_28_NLD11__FUNC_EINT157 (MTK_PIN_NO(28) | 2)
+#define MT8135_PIN_28_NLD11__FUNC_CM2HSYNC_1X (MTK_PIN_NO(28) | 4)
+#define MT8135_PIN_28_NLD11__FUNC_PWM3 (MTK_PIN_NO(28) | 5)
+
+#define MT8135_PIN_29_NLD12__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT8135_PIN_29_NLD12__FUNC_NLD12 (MTK_PIN_NO(29) | 1)
+#define MT8135_PIN_29_NLD12__FUNC_EINT158 (MTK_PIN_NO(29) | 2)
+#define MT8135_PIN_29_NLD12__FUNC_I2SIN_CK (MTK_PIN_NO(29) | 3)
+#define MT8135_PIN_29_NLD12__FUNC_DAC_CK (MTK_PIN_NO(29) | 4)
+#define MT8135_PIN_29_NLD12__FUNC_PCM1_CK (MTK_PIN_NO(29) | 5)
+
+#define MT8135_PIN_30_NLD13__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define MT8135_PIN_30_NLD13__FUNC_NLD13 (MTK_PIN_NO(30) | 1)
+#define MT8135_PIN_30_NLD13__FUNC_EINT159 (MTK_PIN_NO(30) | 2)
+#define MT8135_PIN_30_NLD13__FUNC_I2SIN_WS (MTK_PIN_NO(30) | 3)
+#define MT8135_PIN_30_NLD13__FUNC_DAC_WS (MTK_PIN_NO(30) | 4)
+#define MT8135_PIN_30_NLD13__FUNC_PCM1_WS (MTK_PIN_NO(30) | 5)
+
+#define MT8135_PIN_31_NLD14__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define MT8135_PIN_31_NLD14__FUNC_NLD14 (MTK_PIN_NO(31) | 1)
+#define MT8135_PIN_31_NLD14__FUNC_EINT160 (MTK_PIN_NO(31) | 2)
+#define MT8135_PIN_31_NLD14__FUNC_I2SOUT_DAT (MTK_PIN_NO(31) | 3)
+#define MT8135_PIN_31_NLD14__FUNC_DAC_DAT_OUT (MTK_PIN_NO(31) | 4)
+#define MT8135_PIN_31_NLD14__FUNC_PCM1_DO (MTK_PIN_NO(31) | 5)
+
+#define MT8135_PIN_32_NLD15__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define MT8135_PIN_32_NLD15__FUNC_NLD15 (MTK_PIN_NO(32) | 1)
+#define MT8135_PIN_32_NLD15__FUNC_EINT161 (MTK_PIN_NO(32) | 2)
+#define MT8135_PIN_32_NLD15__FUNC_DISP_PWM (MTK_PIN_NO(32) | 3)
+#define MT8135_PIN_32_NLD15__FUNC_PWM4 (MTK_PIN_NO(32) | 4)
+#define MT8135_PIN_32_NLD15__FUNC_PCM1_DI (MTK_PIN_NO(32) | 5)
+
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(33) | 1)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_EINT50 (MTK_PIN_NO(33) | 2)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_I2SIN_DAT (MTK_PIN_NO(33) | 3)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_PCM1_DI (MTK_PIN_NO(33) | 5)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_SPI1_MI (MTK_PIN_NO(33) | 6)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_NLD10 (MTK_PIN_NO(33) | 7)
+
+#define MT8135_PIN_34_IDDIG__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT8135_PIN_34_IDDIG__FUNC_IDDIG (MTK_PIN_NO(34) | 1)
+#define MT8135_PIN_34_IDDIG__FUNC_EINT34 (MTK_PIN_NO(34) | 2)
+
+#define MT8135_PIN_35_SCL3__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT8135_PIN_35_SCL3__FUNC_SCL3 (MTK_PIN_NO(35) | 1)
+#define MT8135_PIN_35_SCL3__FUNC_EINT96 (MTK_PIN_NO(35) | 2)
+#define MT8135_PIN_35_SCL3__FUNC_CLKM6 (MTK_PIN_NO(35) | 3)
+#define MT8135_PIN_35_SCL3__FUNC_PWM6 (MTK_PIN_NO(35) | 4)
+
+#define MT8135_PIN_36_SDA3__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT8135_PIN_36_SDA3__FUNC_SDA3 (MTK_PIN_NO(36) | 1)
+#define MT8135_PIN_36_SDA3__FUNC_EINT97 (MTK_PIN_NO(36) | 2)
+
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(37) | 1)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_ADC_CK (MTK_PIN_NO(37) | 2)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_HDMI_SDATA0 (MTK_PIN_NO(37) | 3)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_EINT19 (MTK_PIN_NO(37) | 4)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_USB_TEST_IO_6 (MTK_PIN_NO(37) | 5)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_TESTA_OUT19 (MTK_PIN_NO(37) | 7)
+
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(38) | 1)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_ADC_WS (MTK_PIN_NO(38) | 2)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MISO (MTK_PIN_NO(38) | 3)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_EINT21 (MTK_PIN_NO(38) | 4)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_USB_TEST_IO_7 (MTK_PIN_NO(38) | 5)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_TESTA_OUT20 (MTK_PIN_NO(38) | 7)
+
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MISO (MTK_PIN_NO(39) | 1)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_ADC_DAT_IN (MTK_PIN_NO(39) | 2)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(39) | 3)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_EINT20 (MTK_PIN_NO(39) | 4)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_USB_TEST_IO_8 (MTK_PIN_NO(39) | 5)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_TESTA_OUT21 (MTK_PIN_NO(39) | 7)
+
+#define MT8135_PIN_40_DAC_CLK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT8135_PIN_40_DAC_CLK__FUNC_DAC_CK (MTK_PIN_NO(40) | 1)
+#define MT8135_PIN_40_DAC_CLK__FUNC_EINT22 (MTK_PIN_NO(40) | 2)
+#define MT8135_PIN_40_DAC_CLK__FUNC_HDMI_SDATA1 (MTK_PIN_NO(40) | 3)
+#define MT8135_PIN_40_DAC_CLK__FUNC_USB_TEST_IO_9 (MTK_PIN_NO(40) | 5)
+#define MT8135_PIN_40_DAC_CLK__FUNC_TESTA_OUT22 (MTK_PIN_NO(40) | 7)
+
+#define MT8135_PIN_41_DAC_WS__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT8135_PIN_41_DAC_WS__FUNC_DAC_WS (MTK_PIN_NO(41) | 1)
+#define MT8135_PIN_41_DAC_WS__FUNC_EINT24 (MTK_PIN_NO(41) | 2)
+#define MT8135_PIN_41_DAC_WS__FUNC_HDMI_SDATA2 (MTK_PIN_NO(41) | 3)
+#define MT8135_PIN_41_DAC_WS__FUNC_USB_TEST_IO_10 (MTK_PIN_NO(41) | 5)
+#define MT8135_PIN_41_DAC_WS__FUNC_TESTA_OUT23 (MTK_PIN_NO(41) | 7)
+
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(42) | 1)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_EINT23 (MTK_PIN_NO(42) | 2)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_HDMI_SDATA3 (MTK_PIN_NO(42) | 3)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_USB_TEST_IO_11 (MTK_PIN_NO(42) | 5)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_TESTA_OUT24 (MTK_PIN_NO(42) | 7)
+
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(43) | 1)
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_EINT29 (MTK_PIN_NO(43) | 2)
+
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(44) | 1)
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_EINT28 (MTK_PIN_NO(44) | 2)
+
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(45) | 1)
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_EINT27 (MTK_PIN_NO(45) | 2)
+
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(46) | 1)
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_EINT26 (MTK_PIN_NO(46) | 2)
+
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_PWRAP_EVENT_IN (MTK_PIN_NO(47) | 1)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_EINT25 (MTK_PIN_NO(47) | 2)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_TESTA_OUT2 (MTK_PIN_NO(47) | 7)
+
+#define MT8135_PIN_48_RTC32K_CK__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT8135_PIN_48_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(48) | 1)
+
+#define MT8135_PIN_49_WATCHDOG__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT8135_PIN_49_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(49) | 1)
+#define MT8135_PIN_49_WATCHDOG__FUNC_EINT36 (MTK_PIN_NO(49) | 2)
+
+#define MT8135_PIN_50_SRCLKENA__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define MT8135_PIN_50_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(50) | 1)
+#define MT8135_PIN_50_SRCLKENA__FUNC_EINT38 (MTK_PIN_NO(50) | 2)
+
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_SRCVOLTEN (MTK_PIN_NO(51) | 1)
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_EINT37 (MTK_PIN_NO(51) | 2)
+
+#define MT8135_PIN_52_EINT0__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define MT8135_PIN_52_EINT0__FUNC_EINT0 (MTK_PIN_NO(52) | 1)
+#define MT8135_PIN_52_EINT0__FUNC_PWM1 (MTK_PIN_NO(52) | 2)
+#define MT8135_PIN_52_EINT0__FUNC_CLKM0 (MTK_PIN_NO(52) | 3)
+#define MT8135_PIN_52_EINT0__FUNC_SPDIF_OUT (MTK_PIN_NO(52) | 4)
+#define MT8135_PIN_52_EINT0__FUNC_USB_TEST_IO_12 (MTK_PIN_NO(52) | 5)
+#define MT8135_PIN_52_EINT0__FUNC_USB_SCL (MTK_PIN_NO(52) | 7)
+
+#define MT8135_PIN_53_URXD2__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT8135_PIN_53_URXD2__FUNC_URXD2 (MTK_PIN_NO(53) | 1)
+#define MT8135_PIN_53_URXD2__FUNC_EINT83 (MTK_PIN_NO(53) | 2)
+#define MT8135_PIN_53_URXD2__FUNC_HDMI_LRCK (MTK_PIN_NO(53) | 4)
+#define MT8135_PIN_53_URXD2__FUNC_CLKM3 (MTK_PIN_NO(53) | 5)
+#define MT8135_PIN_53_URXD2__FUNC_UTXD2 (MTK_PIN_NO(53) | 7)
+
+#define MT8135_PIN_54_UTXD2__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT8135_PIN_54_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(54) | 1)
+#define MT8135_PIN_54_UTXD2__FUNC_EINT82 (MTK_PIN_NO(54) | 2)
+#define MT8135_PIN_54_UTXD2__FUNC_HDMI_BCK_OUT (MTK_PIN_NO(54) | 4)
+#define MT8135_PIN_54_UTXD2__FUNC_CLKM2 (MTK_PIN_NO(54) | 5)
+#define MT8135_PIN_54_UTXD2__FUNC_URXD2 (MTK_PIN_NO(54) | 7)
+
+#define MT8135_PIN_55_UCTS2__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT8135_PIN_55_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(55) | 1)
+#define MT8135_PIN_55_UCTS2__FUNC_EINT84 (MTK_PIN_NO(55) | 2)
+#define MT8135_PIN_55_UCTS2__FUNC_PWM1 (MTK_PIN_NO(55) | 5)
+#define MT8135_PIN_55_UCTS2__FUNC_URTS2 (MTK_PIN_NO(55) | 7)
+
+#define MT8135_PIN_56_URTS2__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT8135_PIN_56_URTS2__FUNC_URTS2 (MTK_PIN_NO(56) | 1)
+#define MT8135_PIN_56_URTS2__FUNC_EINT85 (MTK_PIN_NO(56) | 2)
+#define MT8135_PIN_56_URTS2__FUNC_PWM2 (MTK_PIN_NO(56) | 5)
+#define MT8135_PIN_56_URTS2__FUNC_UCTS2 (MTK_PIN_NO(56) | 7)
+
+#define MT8135_PIN_57_JTCK__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define MT8135_PIN_57_JTCK__FUNC_JTCK (MTK_PIN_NO(57) | 1)
+#define MT8135_PIN_57_JTCK__FUNC_EINT188 (MTK_PIN_NO(57) | 2)
+#define MT8135_PIN_57_JTCK__FUNC_DSP1_ICK (MTK_PIN_NO(57) | 3)
+
+#define MT8135_PIN_58_JTDO__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define MT8135_PIN_58_JTDO__FUNC_JTDO (MTK_PIN_NO(58) | 1)
+#define MT8135_PIN_58_JTDO__FUNC_EINT190 (MTK_PIN_NO(58) | 2)
+#define MT8135_PIN_58_JTDO__FUNC_DSP2_IMS (MTK_PIN_NO(58) | 3)
+
+#define MT8135_PIN_59_JTRST_B__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define MT8135_PIN_59_JTRST_B__FUNC_JTRST_B (MTK_PIN_NO(59) | 1)
+#define MT8135_PIN_59_JTRST_B__FUNC_EINT0 (MTK_PIN_NO(59) | 2)
+#define MT8135_PIN_59_JTRST_B__FUNC_DSP2_ICK (MTK_PIN_NO(59) | 3)
+
+#define MT8135_PIN_60_JTDI__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define MT8135_PIN_60_JTDI__FUNC_JTDI (MTK_PIN_NO(60) | 1)
+#define MT8135_PIN_60_JTDI__FUNC_EINT189 (MTK_PIN_NO(60) | 2)
+#define MT8135_PIN_60_JTDI__FUNC_DSP1_IMS (MTK_PIN_NO(60) | 3)
+
+#define MT8135_PIN_61_JRTCK__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define MT8135_PIN_61_JRTCK__FUNC_JRTCK (MTK_PIN_NO(61) | 1)
+#define MT8135_PIN_61_JRTCK__FUNC_EINT187 (MTK_PIN_NO(61) | 2)
+#define MT8135_PIN_61_JRTCK__FUNC_DSP1_ID (MTK_PIN_NO(61) | 3)
+
+#define MT8135_PIN_62_JTMS__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define MT8135_PIN_62_JTMS__FUNC_JTMS (MTK_PIN_NO(62) | 1)
+#define MT8135_PIN_62_JTMS__FUNC_EINT191 (MTK_PIN_NO(62) | 2)
+#define MT8135_PIN_62_JTMS__FUNC_DSP2_ID (MTK_PIN_NO(62) | 3)
+
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_MSDC1_INSI (MTK_PIN_NO(63) | 1)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_SCL5 (MTK_PIN_NO(63) | 3)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_PWM6 (MTK_PIN_NO(63) | 4)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_CLKM5 (MTK_PIN_NO(63) | 5)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_TESTB_OUT6 (MTK_PIN_NO(63) | 7)
+
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_MSDC1_SDWPI (MTK_PIN_NO(64) | 1)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_EINT58 (MTK_PIN_NO(64) | 2)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_SDA5 (MTK_PIN_NO(64) | 3)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_PWM7 (MTK_PIN_NO(64) | 4)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_CLKM6 (MTK_PIN_NO(64) | 5)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_TESTB_OUT7 (MTK_PIN_NO(64) | 7)
+
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_MSDC2_INSI (MTK_PIN_NO(65) | 1)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_USB_TEST_IO_27 (MTK_PIN_NO(65) | 5)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_TESTA_OUT3 (MTK_PIN_NO(65) | 7)
+
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_MSDC2_SDWPI (MTK_PIN_NO(66) | 1)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_EINT66 (MTK_PIN_NO(66) | 2)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_USB_TEST_IO_28 (MTK_PIN_NO(66) | 5)
+
+#define MT8135_PIN_67_URXD4__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define MT8135_PIN_67_URXD4__FUNC_URXD4 (MTK_PIN_NO(67) | 1)
+#define MT8135_PIN_67_URXD4__FUNC_EINT89 (MTK_PIN_NO(67) | 2)
+#define MT8135_PIN_67_URXD4__FUNC_URXD1 (MTK_PIN_NO(67) | 3)
+#define MT8135_PIN_67_URXD4__FUNC_UTXD4 (MTK_PIN_NO(67) | 6)
+#define MT8135_PIN_67_URXD4__FUNC_TESTB_OUT10 (MTK_PIN_NO(67) | 7)
+
+#define MT8135_PIN_68_UTXD4__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define MT8135_PIN_68_UTXD4__FUNC_UTXD4 (MTK_PIN_NO(68) | 1)
+#define MT8135_PIN_68_UTXD4__FUNC_EINT88 (MTK_PIN_NO(68) | 2)
+#define MT8135_PIN_68_UTXD4__FUNC_UTXD1 (MTK_PIN_NO(68) | 3)
+#define MT8135_PIN_68_UTXD4__FUNC_URXD4 (MTK_PIN_NO(68) | 6)
+#define MT8135_PIN_68_UTXD4__FUNC_TESTB_OUT11 (MTK_PIN_NO(68) | 7)
+
+#define MT8135_PIN_69_URXD1__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define MT8135_PIN_69_URXD1__FUNC_URXD1 (MTK_PIN_NO(69) | 1)
+#define MT8135_PIN_69_URXD1__FUNC_EINT79 (MTK_PIN_NO(69) | 2)
+#define MT8135_PIN_69_URXD1__FUNC_URXD4 (MTK_PIN_NO(69) | 3)
+#define MT8135_PIN_69_URXD1__FUNC_UTXD1 (MTK_PIN_NO(69) | 6)
+#define MT8135_PIN_69_URXD1__FUNC_TESTB_OUT24 (MTK_PIN_NO(69) | 7)
+
+#define MT8135_PIN_70_UTXD1__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define MT8135_PIN_70_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(70) | 1)
+#define MT8135_PIN_70_UTXD1__FUNC_EINT78 (MTK_PIN_NO(70) | 2)
+#define MT8135_PIN_70_UTXD1__FUNC_UTXD4 (MTK_PIN_NO(70) | 3)
+#define MT8135_PIN_70_UTXD1__FUNC_URXD1 (MTK_PIN_NO(70) | 6)
+#define MT8135_PIN_70_UTXD1__FUNC_TESTB_OUT25 (MTK_PIN_NO(70) | 7)
+
+#define MT8135_PIN_71_UCTS1__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define MT8135_PIN_71_UCTS1__FUNC_UCTS1 (MTK_PIN_NO(71) | 1)
+#define MT8135_PIN_71_UCTS1__FUNC_EINT80 (MTK_PIN_NO(71) | 2)
+#define MT8135_PIN_71_UCTS1__FUNC_CLKM0 (MTK_PIN_NO(71) | 5)
+#define MT8135_PIN_71_UCTS1__FUNC_URTS1 (MTK_PIN_NO(71) | 6)
+#define MT8135_PIN_71_UCTS1__FUNC_TESTB_OUT31 (MTK_PIN_NO(71) | 7)
+
+#define MT8135_PIN_72_URTS1__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT8135_PIN_72_URTS1__FUNC_URTS1 (MTK_PIN_NO(72) | 1)
+#define MT8135_PIN_72_URTS1__FUNC_EINT81 (MTK_PIN_NO(72) | 2)
+#define MT8135_PIN_72_URTS1__FUNC_CLKM1 (MTK_PIN_NO(72) | 5)
+#define MT8135_PIN_72_URTS1__FUNC_UCTS1 (MTK_PIN_NO(72) | 6)
+#define MT8135_PIN_72_URTS1__FUNC_TESTB_OUT21 (MTK_PIN_NO(72) | 7)
+
+#define MT8135_PIN_73_PWM1__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT8135_PIN_73_PWM1__FUNC_PWM1 (MTK_PIN_NO(73) | 1)
+#define MT8135_PIN_73_PWM1__FUNC_EINT73 (MTK_PIN_NO(73) | 2)
+#define MT8135_PIN_73_PWM1__FUNC_USB_DRVVBUS (MTK_PIN_NO(73) | 5)
+#define MT8135_PIN_73_PWM1__FUNC_DISP_PWM (MTK_PIN_NO(73) | 6)
+#define MT8135_PIN_73_PWM1__FUNC_TESTB_OUT8 (MTK_PIN_NO(73) | 7)
+
+#define MT8135_PIN_74_PWM2__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT8135_PIN_74_PWM2__FUNC_PWM2 (MTK_PIN_NO(74) | 1)
+#define MT8135_PIN_74_PWM2__FUNC_EINT74 (MTK_PIN_NO(74) | 2)
+#define MT8135_PIN_74_PWM2__FUNC_DPI33_CK (MTK_PIN_NO(74) | 3)
+#define MT8135_PIN_74_PWM2__FUNC_PWM5 (MTK_PIN_NO(74) | 4)
+#define MT8135_PIN_74_PWM2__FUNC_URXD2 (MTK_PIN_NO(74) | 5)
+#define MT8135_PIN_74_PWM2__FUNC_DISP_PWM (MTK_PIN_NO(74) | 6)
+#define MT8135_PIN_74_PWM2__FUNC_TESTB_OUT9 (MTK_PIN_NO(74) | 7)
+
+#define MT8135_PIN_75_PWM3__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT8135_PIN_75_PWM3__FUNC_PWM3 (MTK_PIN_NO(75) | 1)
+#define MT8135_PIN_75_PWM3__FUNC_EINT75 (MTK_PIN_NO(75) | 2)
+#define MT8135_PIN_75_PWM3__FUNC_DPI33_D0 (MTK_PIN_NO(75) | 3)
+#define MT8135_PIN_75_PWM3__FUNC_PWM6 (MTK_PIN_NO(75) | 4)
+#define MT8135_PIN_75_PWM3__FUNC_UTXD2 (MTK_PIN_NO(75) | 5)
+#define MT8135_PIN_75_PWM3__FUNC_DISP_PWM (MTK_PIN_NO(75) | 6)
+#define MT8135_PIN_75_PWM3__FUNC_TESTB_OUT12 (MTK_PIN_NO(75) | 7)
+
+#define MT8135_PIN_76_PWM4__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT8135_PIN_76_PWM4__FUNC_PWM4 (MTK_PIN_NO(76) | 1)
+#define MT8135_PIN_76_PWM4__FUNC_EINT76 (MTK_PIN_NO(76) | 2)
+#define MT8135_PIN_76_PWM4__FUNC_DPI33_D1 (MTK_PIN_NO(76) | 3)
+#define MT8135_PIN_76_PWM4__FUNC_PWM7 (MTK_PIN_NO(76) | 4)
+#define MT8135_PIN_76_PWM4__FUNC_DISP_PWM (MTK_PIN_NO(76) | 6)
+#define MT8135_PIN_76_PWM4__FUNC_TESTB_OUT13 (MTK_PIN_NO(76) | 7)
+
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(77) | 1)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_EINT63 (MTK_PIN_NO(77) | 2)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DSP2_IMS (MTK_PIN_NO(77) | 4)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DPI33_D6 (MTK_PIN_NO(77) | 6)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_TESTA_OUT25 (MTK_PIN_NO(77) | 7)
+
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(78) | 1)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_EINT64 (MTK_PIN_NO(78) | 2)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DSP2_ID (MTK_PIN_NO(78) | 4)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DPI33_D7 (MTK_PIN_NO(78) | 6)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_TESTA_OUT26 (MTK_PIN_NO(78) | 7)
+
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(79) | 1)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_EINT60 (MTK_PIN_NO(79) | 2)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_DSP1_IMS (MTK_PIN_NO(79) | 4)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_PCM1_WS (MTK_PIN_NO(79) | 5)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_DPI33_D3 (MTK_PIN_NO(79) | 6)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_TESTA_OUT0 (MTK_PIN_NO(79) | 7)
+
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(80) | 1)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_EINT59 (MTK_PIN_NO(80) | 2)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_DSP1_ICK (MTK_PIN_NO(80) | 4)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_PCM1_CK (MTK_PIN_NO(80) | 5)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_DPI33_D2 (MTK_PIN_NO(80) | 6)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_TESTA_OUT1 (MTK_PIN_NO(80) | 7)
+
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(81) | 1)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_EINT62 (MTK_PIN_NO(81) | 2)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DSP2_ICK (MTK_PIN_NO(81) | 4)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_PCM1_DO (MTK_PIN_NO(81) | 5)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DPI33_D5 (MTK_PIN_NO(81) | 6)
+
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(82) | 1)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_EINT61 (MTK_PIN_NO(82) | 2)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DSP1_ID (MTK_PIN_NO(82) | 4)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_PCM1_DI (MTK_PIN_NO(82) | 5)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DPI33_D4 (MTK_PIN_NO(82) | 6)
+
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(83) | 1)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_EINT53 (MTK_PIN_NO(83) | 2)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_SCL1 (MTK_PIN_NO(83) | 3)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_PWM2 (MTK_PIN_NO(83) | 4)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_CLKM1 (MTK_PIN_NO(83) | 5)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_TESTB_OUT2 (MTK_PIN_NO(83) | 7)
+
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(84) | 1)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_EINT54 (MTK_PIN_NO(84) | 2)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_SDA1 (MTK_PIN_NO(84) | 3)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_PWM3 (MTK_PIN_NO(84) | 4)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_CLKM2 (MTK_PIN_NO(84) | 5)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_TESTB_OUT3 (MTK_PIN_NO(84) | 7)
+
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(85) | 1)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_EINT52 (MTK_PIN_NO(85) | 2)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_SDA0 (MTK_PIN_NO(85) | 3)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_PWM1 (MTK_PIN_NO(85) | 4)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_CLKM0 (MTK_PIN_NO(85) | 5)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_TESTB_OUT1 (MTK_PIN_NO(85) | 7)
+
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(86) | 1)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_EINT51 (MTK_PIN_NO(86) | 2)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_SCL0 (MTK_PIN_NO(86) | 3)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_DISP_PWM (MTK_PIN_NO(86) | 4)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_TESTB_OUT0 (MTK_PIN_NO(86) | 7)
+
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(87) | 1)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_EINT55 (MTK_PIN_NO(87) | 2)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_SCL4 (MTK_PIN_NO(87) | 3)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_PWM4 (MTK_PIN_NO(87) | 4)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_CLKM3 (MTK_PIN_NO(87) | 5)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_TESTB_OUT4 (MTK_PIN_NO(87) | 7)
+
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(88) | 1)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_EINT56 (MTK_PIN_NO(88) | 2)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_SDA4 (MTK_PIN_NO(88) | 3)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_PWM5 (MTK_PIN_NO(88) | 4)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_CLKM4 (MTK_PIN_NO(88) | 5)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_TESTB_OUT5 (MTK_PIN_NO(88) | 7)
+
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_MSDC4_DAT0 (MTK_PIN_NO(89) | 1)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EINT133 (MTK_PIN_NO(89) | 2)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(89) | 4)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_USB_DRVVBUS (MTK_PIN_NO(89) | 5)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_A_FUNC_DIN_9 (MTK_PIN_NO(89) | 6)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_LPTE (MTK_PIN_NO(89) | 7)
+
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_MSDC4_DAT1 (MTK_PIN_NO(90) | 1)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_EINT134 (MTK_PIN_NO(90) | 2)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_A_FUNC_DIN_10 (MTK_PIN_NO(90) | 6)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_LRSTB_1X (MTK_PIN_NO(90) | 7)
+
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_MSDC4_DAT5 (MTK_PIN_NO(91) | 1)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_EINT136 (MTK_PIN_NO(91) | 2)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_I2SIN_WS (MTK_PIN_NO(91) | 3)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_DAC_WS (MTK_PIN_NO(91) | 4)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_PCM1_WS (MTK_PIN_NO(91) | 5)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_A_FUNC_DIN_11 (MTK_PIN_NO(91) | 6)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_SPI1_CSN (MTK_PIN_NO(91) | 7)
+
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_MSDC4_DAT6 (MTK_PIN_NO(92) | 1)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_EINT137 (MTK_PIN_NO(92) | 2)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_I2SOUT_DAT (MTK_PIN_NO(92) | 3)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_DAC_DAT_OUT (MTK_PIN_NO(92) | 4)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_PCM1_DO (MTK_PIN_NO(92) | 5)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_A_FUNC_DIN_12 (MTK_PIN_NO(92) | 6)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_SPI1_MO (MTK_PIN_NO(92) | 7)
+
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_MSDC4_DAT7 (MTK_PIN_NO(93) | 1)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_EINT138 (MTK_PIN_NO(93) | 2)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_I2SIN_DAT (MTK_PIN_NO(93) | 3)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_PCM1_DI (MTK_PIN_NO(93) | 5)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_A_FUNC_DIN_13 (MTK_PIN_NO(93) | 6)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_SPI1_MI (MTK_PIN_NO(93) | 7)
+
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_MSDC4_DAT4 (MTK_PIN_NO(94) | 1)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_EINT135 (MTK_PIN_NO(94) | 2)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_I2SIN_CK (MTK_PIN_NO(94) | 3)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_DAC_CK (MTK_PIN_NO(94) | 4)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_PCM1_CK (MTK_PIN_NO(94) | 5)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_A_FUNC_DIN_14 (MTK_PIN_NO(94) | 6)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_SPI1_CLK (MTK_PIN_NO(94) | 7)
+
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_MSDC4_DAT2 (MTK_PIN_NO(95) | 1)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_EINT131 (MTK_PIN_NO(95) | 2)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_I2SIN_WS (MTK_PIN_NO(95) | 3)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_CM2PDN_2X (MTK_PIN_NO(95) | 4)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_DAC_WS (MTK_PIN_NO(95) | 5)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_PCM1_WS (MTK_PIN_NO(95) | 6)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_LSCE0B_1X (MTK_PIN_NO(95) | 7)
+
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_MSDC4_CLK (MTK_PIN_NO(96) | 1)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_EINT129 (MTK_PIN_NO(96) | 2)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_DPI1_CK_2X (MTK_PIN_NO(96) | 3)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_CM2PCLK_2X (MTK_PIN_NO(96) | 4)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_PWM4 (MTK_PIN_NO(96) | 5)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_PCM1_DI (MTK_PIN_NO(96) | 6)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_LSCK_1X (MTK_PIN_NO(96) | 7)
+
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_MSDC4_DAT3 (MTK_PIN_NO(97) | 1)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_EINT132 (MTK_PIN_NO(97) | 2)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_I2SOUT_DAT (MTK_PIN_NO(97) | 3)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_CM2RST_2X (MTK_PIN_NO(97) | 4)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_DAC_DAT_OUT (MTK_PIN_NO(97) | 5)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_PCM1_DO (MTK_PIN_NO(97) | 6)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_LSCE1B_1X (MTK_PIN_NO(97) | 7)
+
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_MSDC4_CMD (MTK_PIN_NO(98) | 1)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_EINT128 (MTK_PIN_NO(98) | 2)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_DPI1_DE_2X (MTK_PIN_NO(98) | 3)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_PWM3 (MTK_PIN_NO(98) | 5)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_LSDA_1X (MTK_PIN_NO(98) | 7)
+
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_MSDC4_RSTB (MTK_PIN_NO(99) | 1)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_EINT130 (MTK_PIN_NO(99) | 2)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_I2SIN_CK (MTK_PIN_NO(99) | 3)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_CM2MCLK_2X (MTK_PIN_NO(99) | 4)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_DAC_CK (MTK_PIN_NO(99) | 5)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_PCM1_CK (MTK_PIN_NO(99) | 6)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_LSA0_1X (MTK_PIN_NO(99) | 7)
+
+#define MT8135_PIN_100_SDA0__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define MT8135_PIN_100_SDA0__FUNC_SDA0 (MTK_PIN_NO(100) | 1)
+#define MT8135_PIN_100_SDA0__FUNC_EINT91 (MTK_PIN_NO(100) | 2)
+#define MT8135_PIN_100_SDA0__FUNC_CLKM1 (MTK_PIN_NO(100) | 3)
+#define MT8135_PIN_100_SDA0__FUNC_PWM1 (MTK_PIN_NO(100) | 4)
+#define MT8135_PIN_100_SDA0__FUNC_A_FUNC_DIN_15 (MTK_PIN_NO(100) | 7)
+
+#define MT8135_PIN_101_SCL0__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define MT8135_PIN_101_SCL0__FUNC_SCL0 (MTK_PIN_NO(101) | 1)
+#define MT8135_PIN_101_SCL0__FUNC_EINT90 (MTK_PIN_NO(101) | 2)
+#define MT8135_PIN_101_SCL0__FUNC_CLKM0 (MTK_PIN_NO(101) | 3)
+#define MT8135_PIN_101_SCL0__FUNC_DISP_PWM (MTK_PIN_NO(101) | 4)
+#define MT8135_PIN_101_SCL0__FUNC_A_FUNC_DIN_16 (MTK_PIN_NO(101) | 7)
+
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_EINT10 (MTK_PIN_NO(102) | 1)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_USB_TEST_IO_16 (MTK_PIN_NO(102) | 5)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_TESTB_OUT16 (MTK_PIN_NO(102) | 6)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_A_FUNC_DIN_17 (MTK_PIN_NO(102) | 7)
+
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_EINT11 (MTK_PIN_NO(103) | 1)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_USB_TEST_IO_17 (MTK_PIN_NO(103) | 5)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_TESTB_OUT17 (MTK_PIN_NO(103) | 6)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_A_FUNC_DIN_18 (MTK_PIN_NO(103) | 7)
+
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_EINT16 (MTK_PIN_NO(104) | 1)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_USB_TEST_IO_18 (MTK_PIN_NO(104) | 5)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_TESTB_OUT18 (MTK_PIN_NO(104) | 6)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_A_FUNC_DIN_19 (MTK_PIN_NO(104) | 7)
+
+#define MT8135_PIN_105_I2S_CLK__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT8135_PIN_105_I2S_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(105) | 1)
+#define MT8135_PIN_105_I2S_CLK__FUNC_EINT10 (MTK_PIN_NO(105) | 2)
+#define MT8135_PIN_105_I2S_CLK__FUNC_DAC_CK (MTK_PIN_NO(105) | 3)
+#define MT8135_PIN_105_I2S_CLK__FUNC_PCM1_CK (MTK_PIN_NO(105) | 4)
+#define MT8135_PIN_105_I2S_CLK__FUNC_USB_TEST_IO_19 (MTK_PIN_NO(105) | 5)
+#define MT8135_PIN_105_I2S_CLK__FUNC_TESTB_OUT19 (MTK_PIN_NO(105) | 6)
+#define MT8135_PIN_105_I2S_CLK__FUNC_A_FUNC_DIN_20 (MTK_PIN_NO(105) | 7)
+
+#define MT8135_PIN_106_I2S_WS__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT8135_PIN_106_I2S_WS__FUNC_I2SIN_WS (MTK_PIN_NO(106) | 1)
+#define MT8135_PIN_106_I2S_WS__FUNC_EINT13 (MTK_PIN_NO(106) | 2)
+#define MT8135_PIN_106_I2S_WS__FUNC_DAC_WS (MTK_PIN_NO(106) | 3)
+#define MT8135_PIN_106_I2S_WS__FUNC_PCM1_WS (MTK_PIN_NO(106) | 4)
+#define MT8135_PIN_106_I2S_WS__FUNC_USB_TEST_IO_20 (MTK_PIN_NO(106) | 5)
+#define MT8135_PIN_106_I2S_WS__FUNC_TESTB_OUT20 (MTK_PIN_NO(106) | 6)
+#define MT8135_PIN_106_I2S_WS__FUNC_A_FUNC_DIN_21 (MTK_PIN_NO(106) | 7)
+
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_I2SIN_DAT (MTK_PIN_NO(107) | 1)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_EINT11 (MTK_PIN_NO(107) | 2)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_PCM1_DI (MTK_PIN_NO(107) | 4)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_USB_TEST_IO_21 (MTK_PIN_NO(107) | 5)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_TESTB_OUT22 (MTK_PIN_NO(107) | 6)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_A_FUNC_DIN_22 (MTK_PIN_NO(107) | 7)
+
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_I2SOUT_DAT (MTK_PIN_NO(108) | 1)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_EINT12 (MTK_PIN_NO(108) | 2)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(108) | 3)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_PCM1_DO (MTK_PIN_NO(108) | 4)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_USB_TEST_IO_22 (MTK_PIN_NO(108) | 5)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_TESTB_OUT23 (MTK_PIN_NO(108) | 6)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_A_FUNC_DIN_23 (MTK_PIN_NO(108) | 7)
+
+#define MT8135_PIN_109_EINT5__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT8135_PIN_109_EINT5__FUNC_EINT5 (MTK_PIN_NO(109) | 1)
+#define MT8135_PIN_109_EINT5__FUNC_PWM5 (MTK_PIN_NO(109) | 2)
+#define MT8135_PIN_109_EINT5__FUNC_CLKM3 (MTK_PIN_NO(109) | 3)
+#define MT8135_PIN_109_EINT5__FUNC_GPU_JTRSTB (MTK_PIN_NO(109) | 4)
+#define MT8135_PIN_109_EINT5__FUNC_USB_TEST_IO_23 (MTK_PIN_NO(109) | 5)
+#define MT8135_PIN_109_EINT5__FUNC_TESTB_OUT26 (MTK_PIN_NO(109) | 6)
+#define MT8135_PIN_109_EINT5__FUNC_A_FUNC_DIN_24 (MTK_PIN_NO(109) | 7)
+
+#define MT8135_PIN_110_EINT6__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT8135_PIN_110_EINT6__FUNC_EINT6 (MTK_PIN_NO(110) | 1)
+#define MT8135_PIN_110_EINT6__FUNC_PWM6 (MTK_PIN_NO(110) | 2)
+#define MT8135_PIN_110_EINT6__FUNC_CLKM4 (MTK_PIN_NO(110) | 3)
+#define MT8135_PIN_110_EINT6__FUNC_GPU_JTMS (MTK_PIN_NO(110) | 4)
+#define MT8135_PIN_110_EINT6__FUNC_USB_TEST_IO_24 (MTK_PIN_NO(110) | 5)
+#define MT8135_PIN_110_EINT6__FUNC_TESTB_OUT27 (MTK_PIN_NO(110) | 6)
+#define MT8135_PIN_110_EINT6__FUNC_A_FUNC_DIN_25 (MTK_PIN_NO(110) | 7)
+
+#define MT8135_PIN_111_EINT7__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT8135_PIN_111_EINT7__FUNC_EINT7 (MTK_PIN_NO(111) | 1)
+#define MT8135_PIN_111_EINT7__FUNC_PWM7 (MTK_PIN_NO(111) | 2)
+#define MT8135_PIN_111_EINT7__FUNC_CLKM5 (MTK_PIN_NO(111) | 3)
+#define MT8135_PIN_111_EINT7__FUNC_GPU_JTDO (MTK_PIN_NO(111) | 4)
+#define MT8135_PIN_111_EINT7__FUNC_USB_TEST_IO_25 (MTK_PIN_NO(111) | 5)
+#define MT8135_PIN_111_EINT7__FUNC_TESTB_OUT28 (MTK_PIN_NO(111) | 6)
+#define MT8135_PIN_111_EINT7__FUNC_A_FUNC_DIN_26 (MTK_PIN_NO(111) | 7)
+
+#define MT8135_PIN_112_EINT8__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT8135_PIN_112_EINT8__FUNC_EINT8 (MTK_PIN_NO(112) | 1)
+#define MT8135_PIN_112_EINT8__FUNC_DISP_PWM (MTK_PIN_NO(112) | 2)
+#define MT8135_PIN_112_EINT8__FUNC_CLKM6 (MTK_PIN_NO(112) | 3)
+#define MT8135_PIN_112_EINT8__FUNC_GPU_JTDI (MTK_PIN_NO(112) | 4)
+#define MT8135_PIN_112_EINT8__FUNC_USB_TEST_IO_26 (MTK_PIN_NO(112) | 5)
+#define MT8135_PIN_112_EINT8__FUNC_TESTB_OUT29 (MTK_PIN_NO(112) | 6)
+#define MT8135_PIN_112_EINT8__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(112) | 7)
+
+#define MT8135_PIN_113_EINT9__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT8135_PIN_113_EINT9__FUNC_EINT9 (MTK_PIN_NO(113) | 1)
+#define MT8135_PIN_113_EINT9__FUNC_GPU_JTCK (MTK_PIN_NO(113) | 4)
+#define MT8135_PIN_113_EINT9__FUNC_USB_DRVVBUS (MTK_PIN_NO(113) | 5)
+#define MT8135_PIN_113_EINT9__FUNC_TESTB_OUT30 (MTK_PIN_NO(113) | 6)
+#define MT8135_PIN_113_EINT9__FUNC_A_FUNC_DIN_27 (MTK_PIN_NO(113) | 7)
+
+#define MT8135_PIN_114_LPCE1B__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT8135_PIN_114_LPCE1B__FUNC_LPCE1B (MTK_PIN_NO(114) | 1)
+#define MT8135_PIN_114_LPCE1B__FUNC_EINT127 (MTK_PIN_NO(114) | 2)
+#define MT8135_PIN_114_LPCE1B__FUNC_PWM2 (MTK_PIN_NO(114) | 5)
+#define MT8135_PIN_114_LPCE1B__FUNC_TESTB_OUT14 (MTK_PIN_NO(114) | 6)
+#define MT8135_PIN_114_LPCE1B__FUNC_A_FUNC_DIN_28 (MTK_PIN_NO(114) | 7)
+
+#define MT8135_PIN_115_LPCE0B__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT8135_PIN_115_LPCE0B__FUNC_LPCE0B (MTK_PIN_NO(115) | 1)
+#define MT8135_PIN_115_LPCE0B__FUNC_EINT126 (MTK_PIN_NO(115) | 2)
+#define MT8135_PIN_115_LPCE0B__FUNC_PWM1 (MTK_PIN_NO(115) | 5)
+#define MT8135_PIN_115_LPCE0B__FUNC_TESTB_OUT15 (MTK_PIN_NO(115) | 6)
+#define MT8135_PIN_115_LPCE0B__FUNC_A_FUNC_DIN_29 (MTK_PIN_NO(115) | 7)
+
+#define MT8135_PIN_116_DISP_PWM__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT8135_PIN_116_DISP_PWM__FUNC_DISP_PWM (MTK_PIN_NO(116) | 1)
+#define MT8135_PIN_116_DISP_PWM__FUNC_EINT77 (MTK_PIN_NO(116) | 2)
+#define MT8135_PIN_116_DISP_PWM__FUNC_LSDI (MTK_PIN_NO(116) | 3)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM1 (MTK_PIN_NO(116) | 4)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM2 (MTK_PIN_NO(116) | 5)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM3 (MTK_PIN_NO(116) | 7)
+
+#define MT8135_PIN_117_EINT1__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT8135_PIN_117_EINT1__FUNC_EINT1 (MTK_PIN_NO(117) | 1)
+#define MT8135_PIN_117_EINT1__FUNC_PWM2 (MTK_PIN_NO(117) | 2)
+#define MT8135_PIN_117_EINT1__FUNC_CLKM1 (MTK_PIN_NO(117) | 3)
+#define MT8135_PIN_117_EINT1__FUNC_USB_TEST_IO_13 (MTK_PIN_NO(117) | 5)
+#define MT8135_PIN_117_EINT1__FUNC_USB_SDA (MTK_PIN_NO(117) | 7)
+
+#define MT8135_PIN_118_EINT2__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT8135_PIN_118_EINT2__FUNC_EINT2 (MTK_PIN_NO(118) | 1)
+#define MT8135_PIN_118_EINT2__FUNC_PWM3 (MTK_PIN_NO(118) | 2)
+#define MT8135_PIN_118_EINT2__FUNC_CLKM2 (MTK_PIN_NO(118) | 3)
+#define MT8135_PIN_118_EINT2__FUNC_USB_TEST_IO_14 (MTK_PIN_NO(118) | 5)
+#define MT8135_PIN_118_EINT2__FUNC_SRCLKENAI2 (MTK_PIN_NO(118) | 6)
+#define MT8135_PIN_118_EINT2__FUNC_A_FUNC_DIN_30 (MTK_PIN_NO(118) | 7)
+
+#define MT8135_PIN_119_EINT3__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT8135_PIN_119_EINT3__FUNC_EINT3 (MTK_PIN_NO(119) | 1)
+#define MT8135_PIN_119_EINT3__FUNC_USB_TEST_IO_15 (MTK_PIN_NO(119) | 5)
+#define MT8135_PIN_119_EINT3__FUNC_SRCLKENAI1 (MTK_PIN_NO(119) | 6)
+#define MT8135_PIN_119_EINT3__FUNC_EXT_26M_CK (MTK_PIN_NO(119) | 7)
+
+#define MT8135_PIN_120_EINT4__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT8135_PIN_120_EINT4__FUNC_EINT4 (MTK_PIN_NO(120) | 1)
+#define MT8135_PIN_120_EINT4__FUNC_PWM4 (MTK_PIN_NO(120) | 2)
+#define MT8135_PIN_120_EINT4__FUNC_USB_DRVVBUS (MTK_PIN_NO(120) | 5)
+#define MT8135_PIN_120_EINT4__FUNC_A_FUNC_DIN_31 (MTK_PIN_NO(120) | 7)
+
+#define MT8135_PIN_121_DPIDE__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT8135_PIN_121_DPIDE__FUNC_DPI0_DE (MTK_PIN_NO(121) | 1)
+#define MT8135_PIN_121_DPIDE__FUNC_EINT100 (MTK_PIN_NO(121) | 2)
+#define MT8135_PIN_121_DPIDE__FUNC_I2SOUT_DAT (MTK_PIN_NO(121) | 3)
+#define MT8135_PIN_121_DPIDE__FUNC_DAC_DAT_OUT (MTK_PIN_NO(121) | 4)
+#define MT8135_PIN_121_DPIDE__FUNC_PCM1_DO (MTK_PIN_NO(121) | 5)
+#define MT8135_PIN_121_DPIDE__FUNC_IRDA_TXD (MTK_PIN_NO(121) | 6)
+
+#define MT8135_PIN_122_DPICK__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT8135_PIN_122_DPICK__FUNC_DPI0_CK (MTK_PIN_NO(122) | 1)
+#define MT8135_PIN_122_DPICK__FUNC_EINT101 (MTK_PIN_NO(122) | 2)
+#define MT8135_PIN_122_DPICK__FUNC_I2SIN_DAT (MTK_PIN_NO(122) | 3)
+#define MT8135_PIN_122_DPICK__FUNC_PCM1_DI (MTK_PIN_NO(122) | 5)
+#define MT8135_PIN_122_DPICK__FUNC_IRDA_PDN (MTK_PIN_NO(122) | 6)
+
+#define MT8135_PIN_123_DPIG4__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT8135_PIN_123_DPIG4__FUNC_DPI0_G4 (MTK_PIN_NO(123) | 1)
+#define MT8135_PIN_123_DPIG4__FUNC_EINT114 (MTK_PIN_NO(123) | 2)
+#define MT8135_PIN_123_DPIG4__FUNC_CM2DAT_2X_0 (MTK_PIN_NO(123) | 4)
+#define MT8135_PIN_123_DPIG4__FUNC_DSP2_ID (MTK_PIN_NO(123) | 5)
+
+#define MT8135_PIN_124_DPIG5__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT8135_PIN_124_DPIG5__FUNC_DPI0_G5 (MTK_PIN_NO(124) | 1)
+#define MT8135_PIN_124_DPIG5__FUNC_EINT115 (MTK_PIN_NO(124) | 2)
+#define MT8135_PIN_124_DPIG5__FUNC_CM2DAT_2X_1 (MTK_PIN_NO(124) | 4)
+#define MT8135_PIN_124_DPIG5__FUNC_DSP2_ICK (MTK_PIN_NO(124) | 5)
+
+#define MT8135_PIN_125_DPIR3__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT8135_PIN_125_DPIR3__FUNC_DPI0_R3 (MTK_PIN_NO(125) | 1)
+#define MT8135_PIN_125_DPIR3__FUNC_EINT121 (MTK_PIN_NO(125) | 2)
+#define MT8135_PIN_125_DPIR3__FUNC_CM2DAT_2X_7 (MTK_PIN_NO(125) | 4)
+
+#define MT8135_PIN_126_DPIG1__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT8135_PIN_126_DPIG1__FUNC_DPI0_G1 (MTK_PIN_NO(126) | 1)
+#define MT8135_PIN_126_DPIG1__FUNC_EINT111 (MTK_PIN_NO(126) | 2)
+#define MT8135_PIN_126_DPIG1__FUNC_DSP1_ICK (MTK_PIN_NO(126) | 5)
+
+#define MT8135_PIN_127_DPIVSYNC__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_DPI0_VSYNC (MTK_PIN_NO(127) | 1)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_EINT98 (MTK_PIN_NO(127) | 2)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_I2SIN_CK (MTK_PIN_NO(127) | 3)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_DAC_CK (MTK_PIN_NO(127) | 4)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_PCM1_CK (MTK_PIN_NO(127) | 5)
+
+#define MT8135_PIN_128_DPIHSYNC__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_DPI0_HSYNC (MTK_PIN_NO(128) | 1)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_EINT99 (MTK_PIN_NO(128) | 2)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_I2SIN_WS (MTK_PIN_NO(128) | 3)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_DAC_WS (MTK_PIN_NO(128) | 4)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_PCM1_WS (MTK_PIN_NO(128) | 5)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_IRDA_RXD (MTK_PIN_NO(128) | 6)
+
+#define MT8135_PIN_129_DPIB0__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define MT8135_PIN_129_DPIB0__FUNC_DPI0_B0 (MTK_PIN_NO(129) | 1)
+#define MT8135_PIN_129_DPIB0__FUNC_EINT102 (MTK_PIN_NO(129) | 2)
+#define MT8135_PIN_129_DPIB0__FUNC_SCL0 (MTK_PIN_NO(129) | 4)
+#define MT8135_PIN_129_DPIB0__FUNC_DISP_PWM (MTK_PIN_NO(129) | 5)
+
+#define MT8135_PIN_130_DPIB1__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define MT8135_PIN_130_DPIB1__FUNC_DPI0_B1 (MTK_PIN_NO(130) | 1)
+#define MT8135_PIN_130_DPIB1__FUNC_EINT103 (MTK_PIN_NO(130) | 2)
+#define MT8135_PIN_130_DPIB1__FUNC_CLKM0 (MTK_PIN_NO(130) | 3)
+#define MT8135_PIN_130_DPIB1__FUNC_SDA0 (MTK_PIN_NO(130) | 4)
+#define MT8135_PIN_130_DPIB1__FUNC_PWM1 (MTK_PIN_NO(130) | 5)
+
+#define MT8135_PIN_131_DPIB2__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define MT8135_PIN_131_DPIB2__FUNC_DPI0_B2 (MTK_PIN_NO(131) | 1)
+#define MT8135_PIN_131_DPIB2__FUNC_EINT104 (MTK_PIN_NO(131) | 2)
+#define MT8135_PIN_131_DPIB2__FUNC_CLKM1 (MTK_PIN_NO(131) | 3)
+#define MT8135_PIN_131_DPIB2__FUNC_SCL1 (MTK_PIN_NO(131) | 4)
+#define MT8135_PIN_131_DPIB2__FUNC_PWM2 (MTK_PIN_NO(131) | 5)
+
+#define MT8135_PIN_132_DPIB3__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define MT8135_PIN_132_DPIB3__FUNC_DPI0_B3 (MTK_PIN_NO(132) | 1)
+#define MT8135_PIN_132_DPIB3__FUNC_EINT105 (MTK_PIN_NO(132) | 2)
+#define MT8135_PIN_132_DPIB3__FUNC_CLKM2 (MTK_PIN_NO(132) | 3)
+#define MT8135_PIN_132_DPIB3__FUNC_SDA1 (MTK_PIN_NO(132) | 4)
+#define MT8135_PIN_132_DPIB3__FUNC_PWM3 (MTK_PIN_NO(132) | 5)
+
+#define MT8135_PIN_133_DPIB4__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define MT8135_PIN_133_DPIB4__FUNC_DPI0_B4 (MTK_PIN_NO(133) | 1)
+#define MT8135_PIN_133_DPIB4__FUNC_EINT106 (MTK_PIN_NO(133) | 2)
+#define MT8135_PIN_133_DPIB4__FUNC_CLKM3 (MTK_PIN_NO(133) | 3)
+#define MT8135_PIN_133_DPIB4__FUNC_SCL2 (MTK_PIN_NO(133) | 4)
+#define MT8135_PIN_133_DPIB4__FUNC_PWM4 (MTK_PIN_NO(133) | 5)
+
+#define MT8135_PIN_134_DPIB5__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define MT8135_PIN_134_DPIB5__FUNC_DPI0_B5 (MTK_PIN_NO(134) | 1)
+#define MT8135_PIN_134_DPIB5__FUNC_EINT107 (MTK_PIN_NO(134) | 2)
+#define MT8135_PIN_134_DPIB5__FUNC_CLKM4 (MTK_PIN_NO(134) | 3)
+#define MT8135_PIN_134_DPIB5__FUNC_SDA2 (MTK_PIN_NO(134) | 4)
+#define MT8135_PIN_134_DPIB5__FUNC_PWM5 (MTK_PIN_NO(134) | 5)
+
+#define MT8135_PIN_135_DPIB6__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
+#define MT8135_PIN_135_DPIB6__FUNC_DPI0_B6 (MTK_PIN_NO(135) | 1)
+#define MT8135_PIN_135_DPIB6__FUNC_EINT108 (MTK_PIN_NO(135) | 2)
+#define MT8135_PIN_135_DPIB6__FUNC_CLKM5 (MTK_PIN_NO(135) | 3)
+#define MT8135_PIN_135_DPIB6__FUNC_SCL3 (MTK_PIN_NO(135) | 4)
+#define MT8135_PIN_135_DPIB6__FUNC_PWM6 (MTK_PIN_NO(135) | 5)
+
+#define MT8135_PIN_136_DPIB7__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
+#define MT8135_PIN_136_DPIB7__FUNC_DPI0_B7 (MTK_PIN_NO(136) | 1)
+#define MT8135_PIN_136_DPIB7__FUNC_EINT109 (MTK_PIN_NO(136) | 2)
+#define MT8135_PIN_136_DPIB7__FUNC_CLKM6 (MTK_PIN_NO(136) | 3)
+#define MT8135_PIN_136_DPIB7__FUNC_SDA3 (MTK_PIN_NO(136) | 4)
+#define MT8135_PIN_136_DPIB7__FUNC_PWM7 (MTK_PIN_NO(136) | 5)
+
+#define MT8135_PIN_137_DPIG0__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
+#define MT8135_PIN_137_DPIG0__FUNC_DPI0_G0 (MTK_PIN_NO(137) | 1)
+#define MT8135_PIN_137_DPIG0__FUNC_EINT110 (MTK_PIN_NO(137) | 2)
+#define MT8135_PIN_137_DPIG0__FUNC_DSP1_ID (MTK_PIN_NO(137) | 5)
+
+#define MT8135_PIN_138_DPIG2__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
+#define MT8135_PIN_138_DPIG2__FUNC_DPI0_G2 (MTK_PIN_NO(138) | 1)
+#define MT8135_PIN_138_DPIG2__FUNC_EINT112 (MTK_PIN_NO(138) | 2)
+#define MT8135_PIN_138_DPIG2__FUNC_DSP1_IMS (MTK_PIN_NO(138) | 5)
+
+#define MT8135_PIN_139_DPIG3__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
+#define MT8135_PIN_139_DPIG3__FUNC_DPI0_G3 (MTK_PIN_NO(139) | 1)
+#define MT8135_PIN_139_DPIG3__FUNC_EINT113 (MTK_PIN_NO(139) | 2)
+#define MT8135_PIN_139_DPIG3__FUNC_DSP2_IMS (MTK_PIN_NO(139) | 5)
+
+#define MT8135_PIN_140_DPIG6__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
+#define MT8135_PIN_140_DPIG6__FUNC_DPI0_G6 (MTK_PIN_NO(140) | 1)
+#define MT8135_PIN_140_DPIG6__FUNC_EINT116 (MTK_PIN_NO(140) | 2)
+#define MT8135_PIN_140_DPIG6__FUNC_CM2DAT_2X_2 (MTK_PIN_NO(140) | 4)
+
+#define MT8135_PIN_141_DPIG7__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
+#define MT8135_PIN_141_DPIG7__FUNC_DPI0_G7 (MTK_PIN_NO(141) | 1)
+#define MT8135_PIN_141_DPIG7__FUNC_EINT117 (MTK_PIN_NO(141) | 2)
+#define MT8135_PIN_141_DPIG7__FUNC_CM2DAT_2X_3 (MTK_PIN_NO(141) | 4)
+
+#define MT8135_PIN_142_DPIR0__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
+#define MT8135_PIN_142_DPIR0__FUNC_DPI0_R0 (MTK_PIN_NO(142) | 1)
+#define MT8135_PIN_142_DPIR0__FUNC_EINT118 (MTK_PIN_NO(142) | 2)
+#define MT8135_PIN_142_DPIR0__FUNC_CM2DAT_2X_4 (MTK_PIN_NO(142) | 4)
+
+#define MT8135_PIN_143_DPIR1__FUNC_GPIO143 (MTK_PIN_NO(143) | 0)
+#define MT8135_PIN_143_DPIR1__FUNC_DPI0_R1 (MTK_PIN_NO(143) | 1)
+#define MT8135_PIN_143_DPIR1__FUNC_EINT119 (MTK_PIN_NO(143) | 2)
+#define MT8135_PIN_143_DPIR1__FUNC_CM2DAT_2X_5 (MTK_PIN_NO(143) | 4)
+
+#define MT8135_PIN_144_DPIR2__FUNC_GPIO144 (MTK_PIN_NO(144) | 0)
+#define MT8135_PIN_144_DPIR2__FUNC_DPI0_R2 (MTK_PIN_NO(144) | 1)
+#define MT8135_PIN_144_DPIR2__FUNC_EINT120 (MTK_PIN_NO(144) | 2)
+#define MT8135_PIN_144_DPIR2__FUNC_CM2DAT_2X_6 (MTK_PIN_NO(144) | 4)
+
+#define MT8135_PIN_145_DPIR4__FUNC_GPIO145 (MTK_PIN_NO(145) | 0)
+#define MT8135_PIN_145_DPIR4__FUNC_DPI0_R4 (MTK_PIN_NO(145) | 1)
+#define MT8135_PIN_145_DPIR4__FUNC_EINT122 (MTK_PIN_NO(145) | 2)
+#define MT8135_PIN_145_DPIR4__FUNC_CM2DAT_2X_8 (MTK_PIN_NO(145) | 4)
+
+#define MT8135_PIN_146_DPIR5__FUNC_GPIO146 (MTK_PIN_NO(146) | 0)
+#define MT8135_PIN_146_DPIR5__FUNC_DPI0_R5 (MTK_PIN_NO(146) | 1)
+#define MT8135_PIN_146_DPIR5__FUNC_EINT123 (MTK_PIN_NO(146) | 2)
+#define MT8135_PIN_146_DPIR5__FUNC_CM2DAT_2X_9 (MTK_PIN_NO(146) | 4)
+
+#define MT8135_PIN_147_DPIR6__FUNC_GPIO147 (MTK_PIN_NO(147) | 0)
+#define MT8135_PIN_147_DPIR6__FUNC_DPI0_R6 (MTK_PIN_NO(147) | 1)
+#define MT8135_PIN_147_DPIR6__FUNC_EINT124 (MTK_PIN_NO(147) | 2)
+#define MT8135_PIN_147_DPIR6__FUNC_CM2VSYNC_2X (MTK_PIN_NO(147) | 4)
+
+#define MT8135_PIN_148_DPIR7__FUNC_GPIO148 (MTK_PIN_NO(148) | 0)
+#define MT8135_PIN_148_DPIR7__FUNC_DPI0_R7 (MTK_PIN_NO(148) | 1)
+#define MT8135_PIN_148_DPIR7__FUNC_EINT125 (MTK_PIN_NO(148) | 2)
+#define MT8135_PIN_148_DPIR7__FUNC_CM2HSYNC_2X (MTK_PIN_NO(148) | 4)
+
+#define MT8135_PIN_149_TDN3__FUNC_GPIO149 (MTK_PIN_NO(149) | 0)
+#define MT8135_PIN_149_TDN3__FUNC_EINT36 (MTK_PIN_NO(149) | 2)
+
+#define MT8135_PIN_150_TDP3__FUNC_GPIO150 (MTK_PIN_NO(150) | 0)
+#define MT8135_PIN_150_TDP3__FUNC_EINT35 (MTK_PIN_NO(150) | 2)
+
+#define MT8135_PIN_151_TDN2__FUNC_GPIO151 (MTK_PIN_NO(151) | 0)
+#define MT8135_PIN_151_TDN2__FUNC_EINT169 (MTK_PIN_NO(151) | 2)
+
+#define MT8135_PIN_152_TDP2__FUNC_GPIO152 (MTK_PIN_NO(152) | 0)
+#define MT8135_PIN_152_TDP2__FUNC_EINT168 (MTK_PIN_NO(152) | 2)
+
+#define MT8135_PIN_153_TCN__FUNC_GPIO153 (MTK_PIN_NO(153) | 0)
+#define MT8135_PIN_153_TCN__FUNC_EINT163 (MTK_PIN_NO(153) | 2)
+
+#define MT8135_PIN_154_TCP__FUNC_GPIO154 (MTK_PIN_NO(154) | 0)
+#define MT8135_PIN_154_TCP__FUNC_EINT162 (MTK_PIN_NO(154) | 2)
+
+#define MT8135_PIN_155_TDN1__FUNC_GPIO155 (MTK_PIN_NO(155) | 0)
+#define MT8135_PIN_155_TDN1__FUNC_EINT167 (MTK_PIN_NO(155) | 2)
+
+#define MT8135_PIN_156_TDP1__FUNC_GPIO156 (MTK_PIN_NO(156) | 0)
+#define MT8135_PIN_156_TDP1__FUNC_EINT166 (MTK_PIN_NO(156) | 2)
+
+#define MT8135_PIN_157_TDN0__FUNC_GPIO157 (MTK_PIN_NO(157) | 0)
+#define MT8135_PIN_157_TDN0__FUNC_EINT165 (MTK_PIN_NO(157) | 2)
+
+#define MT8135_PIN_158_TDP0__FUNC_GPIO158 (MTK_PIN_NO(158) | 0)
+#define MT8135_PIN_158_TDP0__FUNC_EINT164 (MTK_PIN_NO(158) | 2)
+
+#define MT8135_PIN_159_RDN3__FUNC_GPIO159 (MTK_PIN_NO(159) | 0)
+#define MT8135_PIN_159_RDN3__FUNC_EINT18 (MTK_PIN_NO(159) | 2)
+
+#define MT8135_PIN_160_RDP3__FUNC_GPIO160 (MTK_PIN_NO(160) | 0)
+#define MT8135_PIN_160_RDP3__FUNC_EINT30 (MTK_PIN_NO(160) | 2)
+
+#define MT8135_PIN_161_RDN2__FUNC_GPIO161 (MTK_PIN_NO(161) | 0)
+#define MT8135_PIN_161_RDN2__FUNC_EINT31 (MTK_PIN_NO(161) | 2)
+
+#define MT8135_PIN_162_RDP2__FUNC_GPIO162 (MTK_PIN_NO(162) | 0)
+#define MT8135_PIN_162_RDP2__FUNC_EINT32 (MTK_PIN_NO(162) | 2)
+
+#define MT8135_PIN_163_RCN__FUNC_GPIO163 (MTK_PIN_NO(163) | 0)
+#define MT8135_PIN_163_RCN__FUNC_EINT33 (MTK_PIN_NO(163) | 2)
+
+#define MT8135_PIN_164_RCP__FUNC_GPIO164 (MTK_PIN_NO(164) | 0)
+#define MT8135_PIN_164_RCP__FUNC_EINT39 (MTK_PIN_NO(164) | 2)
+
+#define MT8135_PIN_165_RDN1__FUNC_GPIO165 (MTK_PIN_NO(165) | 0)
+
+#define MT8135_PIN_166_RDP1__FUNC_GPIO166 (MTK_PIN_NO(166) | 0)
+
+#define MT8135_PIN_167_RDN0__FUNC_GPIO167 (MTK_PIN_NO(167) | 0)
+
+#define MT8135_PIN_168_RDP0__FUNC_GPIO168 (MTK_PIN_NO(168) | 0)
+
+#define MT8135_PIN_169_RDN1_A__FUNC_GPIO169 (MTK_PIN_NO(169) | 0)
+#define MT8135_PIN_169_RDN1_A__FUNC_CMDAT6 (MTK_PIN_NO(169) | 1)
+#define MT8135_PIN_169_RDN1_A__FUNC_EINT175 (MTK_PIN_NO(169) | 2)
+
+#define MT8135_PIN_170_RDP1_A__FUNC_GPIO170 (MTK_PIN_NO(170) | 0)
+#define MT8135_PIN_170_RDP1_A__FUNC_CMDAT7 (MTK_PIN_NO(170) | 1)
+#define MT8135_PIN_170_RDP1_A__FUNC_EINT174 (MTK_PIN_NO(170) | 2)
+
+#define MT8135_PIN_171_RCN_A__FUNC_GPIO171 (MTK_PIN_NO(171) | 0)
+#define MT8135_PIN_171_RCN_A__FUNC_CMDAT8 (MTK_PIN_NO(171) | 1)
+#define MT8135_PIN_171_RCN_A__FUNC_EINT171 (MTK_PIN_NO(171) | 2)
+
+#define MT8135_PIN_172_RCP_A__FUNC_GPIO172 (MTK_PIN_NO(172) | 0)
+#define MT8135_PIN_172_RCP_A__FUNC_CMDAT9 (MTK_PIN_NO(172) | 1)
+#define MT8135_PIN_172_RCP_A__FUNC_EINT170 (MTK_PIN_NO(172) | 2)
+
+#define MT8135_PIN_173_RDN0_A__FUNC_GPIO173 (MTK_PIN_NO(173) | 0)
+#define MT8135_PIN_173_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(173) | 1)
+#define MT8135_PIN_173_RDN0_A__FUNC_EINT173 (MTK_PIN_NO(173) | 2)
+
+#define MT8135_PIN_174_RDP0_A__FUNC_GPIO174 (MTK_PIN_NO(174) | 0)
+#define MT8135_PIN_174_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(174) | 1)
+#define MT8135_PIN_174_RDP0_A__FUNC_EINT172 (MTK_PIN_NO(174) | 2)
+
+#define MT8135_PIN_175_RDN1_B__FUNC_GPIO175 (MTK_PIN_NO(175) | 0)
+#define MT8135_PIN_175_RDN1_B__FUNC_CMDAT2 (MTK_PIN_NO(175) | 1)
+#define MT8135_PIN_175_RDN1_B__FUNC_EINT181 (MTK_PIN_NO(175) | 2)
+#define MT8135_PIN_175_RDN1_B__FUNC_CMCSD2 (MTK_PIN_NO(175) | 3)
+
+#define MT8135_PIN_176_RDP1_B__FUNC_GPIO176 (MTK_PIN_NO(176) | 0)
+#define MT8135_PIN_176_RDP1_B__FUNC_CMDAT3 (MTK_PIN_NO(176) | 1)
+#define MT8135_PIN_176_RDP1_B__FUNC_EINT180 (MTK_PIN_NO(176) | 2)
+#define MT8135_PIN_176_RDP1_B__FUNC_CMCSD3 (MTK_PIN_NO(176) | 3)
+
+#define MT8135_PIN_177_RCN_B__FUNC_GPIO177 (MTK_PIN_NO(177) | 0)
+#define MT8135_PIN_177_RCN_B__FUNC_CMDAT4 (MTK_PIN_NO(177) | 1)
+#define MT8135_PIN_177_RCN_B__FUNC_EINT177 (MTK_PIN_NO(177) | 2)
+
+#define MT8135_PIN_178_RCP_B__FUNC_GPIO178 (MTK_PIN_NO(178) | 0)
+#define MT8135_PIN_178_RCP_B__FUNC_CMDAT5 (MTK_PIN_NO(178) | 1)
+#define MT8135_PIN_178_RCP_B__FUNC_EINT176 (MTK_PIN_NO(178) | 2)
+
+#define MT8135_PIN_179_RDN0_B__FUNC_GPIO179 (MTK_PIN_NO(179) | 0)
+#define MT8135_PIN_179_RDN0_B__FUNC_CMDAT0 (MTK_PIN_NO(179) | 1)
+#define MT8135_PIN_179_RDN0_B__FUNC_EINT179 (MTK_PIN_NO(179) | 2)
+#define MT8135_PIN_179_RDN0_B__FUNC_CMCSD0 (MTK_PIN_NO(179) | 3)
+
+#define MT8135_PIN_180_RDP0_B__FUNC_GPIO180 (MTK_PIN_NO(180) | 0)
+#define MT8135_PIN_180_RDP0_B__FUNC_CMDAT1 (MTK_PIN_NO(180) | 1)
+#define MT8135_PIN_180_RDP0_B__FUNC_EINT178 (MTK_PIN_NO(180) | 2)
+#define MT8135_PIN_180_RDP0_B__FUNC_CMCSD1 (MTK_PIN_NO(180) | 3)
+
+#define MT8135_PIN_181_CMPCLK__FUNC_GPIO181 (MTK_PIN_NO(181) | 0)
+#define MT8135_PIN_181_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(181) | 1)
+#define MT8135_PIN_181_CMPCLK__FUNC_EINT182 (MTK_PIN_NO(181) | 2)
+#define MT8135_PIN_181_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(181) | 3)
+#define MT8135_PIN_181_CMPCLK__FUNC_CM2MCLK_4X (MTK_PIN_NO(181) | 4)
+#define MT8135_PIN_181_CMPCLK__FUNC_TS_AUXADC_SEL_3 (MTK_PIN_NO(181) | 5)
+#define MT8135_PIN_181_CMPCLK__FUNC_VENC_TEST_CK (MTK_PIN_NO(181) | 6)
+#define MT8135_PIN_181_CMPCLK__FUNC_TESTA_OUT27 (MTK_PIN_NO(181) | 7)
+
+#define MT8135_PIN_182_CMMCLK__FUNC_GPIO182 (MTK_PIN_NO(182) | 0)
+#define MT8135_PIN_182_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(182) | 1)
+#define MT8135_PIN_182_CMMCLK__FUNC_EINT183 (MTK_PIN_NO(182) | 2)
+#define MT8135_PIN_182_CMMCLK__FUNC_TS_AUXADC_SEL_2 (MTK_PIN_NO(182) | 5)
+#define MT8135_PIN_182_CMMCLK__FUNC_TESTA_OUT28 (MTK_PIN_NO(182) | 7)
+
+#define MT8135_PIN_183_CMRST__FUNC_GPIO183 (MTK_PIN_NO(183) | 0)
+#define MT8135_PIN_183_CMRST__FUNC_CMRST (MTK_PIN_NO(183) | 1)
+#define MT8135_PIN_183_CMRST__FUNC_EINT185 (MTK_PIN_NO(183) | 2)
+#define MT8135_PIN_183_CMRST__FUNC_TS_AUXADC_SEL_1 (MTK_PIN_NO(183) | 5)
+#define MT8135_PIN_183_CMRST__FUNC_TESTA_OUT30 (MTK_PIN_NO(183) | 7)
+
+#define MT8135_PIN_184_CMPDN__FUNC_GPIO184 (MTK_PIN_NO(184) | 0)
+#define MT8135_PIN_184_CMPDN__FUNC_CMPDN (MTK_PIN_NO(184) | 1)
+#define MT8135_PIN_184_CMPDN__FUNC_EINT184 (MTK_PIN_NO(184) | 2)
+#define MT8135_PIN_184_CMPDN__FUNC_TS_AUXADC_SEL_0 (MTK_PIN_NO(184) | 5)
+#define MT8135_PIN_184_CMPDN__FUNC_TESTA_OUT29 (MTK_PIN_NO(184) | 7)
+
+#define MT8135_PIN_185_CMFLASH__FUNC_GPIO185 (MTK_PIN_NO(185) | 0)
+#define MT8135_PIN_185_CMFLASH__FUNC_CMFLASH (MTK_PIN_NO(185) | 1)
+#define MT8135_PIN_185_CMFLASH__FUNC_EINT186 (MTK_PIN_NO(185) | 2)
+#define MT8135_PIN_185_CMFLASH__FUNC_CM2MCLK_3X (MTK_PIN_NO(185) | 3)
+#define MT8135_PIN_185_CMFLASH__FUNC_MFG_TEST_CK_1 (MTK_PIN_NO(185) | 6)
+#define MT8135_PIN_185_CMFLASH__FUNC_TESTA_OUT31 (MTK_PIN_NO(185) | 7)
+
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_GPIO186 (MTK_PIN_NO(186) | 0)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_MRG_I2S_P_CLK (MTK_PIN_NO(186) | 1)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_EINT14 (MTK_PIN_NO(186) | 2)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(186) | 3)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_PCM0_CK (MTK_PIN_NO(186) | 4)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_DSP2_ICK (MTK_PIN_NO(186) | 5)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_IMG_TEST_CK (MTK_PIN_NO(186) | 6)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_USB_SCL (MTK_PIN_NO(186) | 7)
+
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_GPIO187 (MTK_PIN_NO(187) | 0)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_MRG_I2S_SYNC (MTK_PIN_NO(187) | 1)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_EINT16 (MTK_PIN_NO(187) | 2)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_I2SIN_WS (MTK_PIN_NO(187) | 3)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_PCM0_WS (MTK_PIN_NO(187) | 4)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_DISP_TEST_CK (MTK_PIN_NO(187) | 6)
+
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_GPIO188 (MTK_PIN_NO(188) | 0)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MRG_I2S_PCM_RX (MTK_PIN_NO(188) | 1)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_EINT15 (MTK_PIN_NO(188) | 2)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_I2SIN_DAT (MTK_PIN_NO(188) | 3)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_PCM0_DI (MTK_PIN_NO(188) | 4)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_DSP2_ID (MTK_PIN_NO(188) | 5)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MFG_TEST_CK (MTK_PIN_NO(188) | 6)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_USB_SDA (MTK_PIN_NO(188) | 7)
+
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_GPIO189 (MTK_PIN_NO(189) | 0)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_MRG_I2S_PCM_TX (MTK_PIN_NO(189) | 1)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_EINT17 (MTK_PIN_NO(189) | 2)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_I2SOUT_DAT (MTK_PIN_NO(189) | 3)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_PCM0_DO (MTK_PIN_NO(189) | 4)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_VDEC_TEST_CK (MTK_PIN_NO(189) | 6)
+
+#define MT8135_PIN_190_SRCLKENAI__FUNC_GPIO190 (MTK_PIN_NO(190) | 0)
+#define MT8135_PIN_190_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(190) | 1)
+
+#define MT8135_PIN_191_URXD3__FUNC_GPIO191 (MTK_PIN_NO(191) | 0)
+#define MT8135_PIN_191_URXD3__FUNC_URXD3 (MTK_PIN_NO(191) | 1)
+#define MT8135_PIN_191_URXD3__FUNC_EINT87 (MTK_PIN_NO(191) | 2)
+#define MT8135_PIN_191_URXD3__FUNC_UTXD3 (MTK_PIN_NO(191) | 3)
+#define MT8135_PIN_191_URXD3__FUNC_TS_AUX_ST (MTK_PIN_NO(191) | 5)
+#define MT8135_PIN_191_URXD3__FUNC_PWM4 (MTK_PIN_NO(191) | 6)
+
+#define MT8135_PIN_192_UTXD3__FUNC_GPIO192 (MTK_PIN_NO(192) | 0)
+#define MT8135_PIN_192_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(192) | 1)
+#define MT8135_PIN_192_UTXD3__FUNC_EINT86 (MTK_PIN_NO(192) | 2)
+#define MT8135_PIN_192_UTXD3__FUNC_URXD3 (MTK_PIN_NO(192) | 3)
+#define MT8135_PIN_192_UTXD3__FUNC_TS_AUX_CS_B (MTK_PIN_NO(192) | 5)
+#define MT8135_PIN_192_UTXD3__FUNC_PWM3 (MTK_PIN_NO(192) | 6)
+
+#define MT8135_PIN_193_SDA2__FUNC_GPIO193 (MTK_PIN_NO(193) | 0)
+#define MT8135_PIN_193_SDA2__FUNC_SDA2 (MTK_PIN_NO(193) | 1)
+#define MT8135_PIN_193_SDA2__FUNC_EINT95 (MTK_PIN_NO(193) | 2)
+#define MT8135_PIN_193_SDA2__FUNC_CLKM5 (MTK_PIN_NO(193) | 3)
+#define MT8135_PIN_193_SDA2__FUNC_PWM5 (MTK_PIN_NO(193) | 4)
+#define MT8135_PIN_193_SDA2__FUNC_TS_AUX_PWDB (MTK_PIN_NO(193) | 5)
+
+#define MT8135_PIN_194_SCL2__FUNC_GPIO194 (MTK_PIN_NO(194) | 0)
+#define MT8135_PIN_194_SCL2__FUNC_SCL2 (MTK_PIN_NO(194) | 1)
+#define MT8135_PIN_194_SCL2__FUNC_EINT94 (MTK_PIN_NO(194) | 2)
+#define MT8135_PIN_194_SCL2__FUNC_CLKM4 (MTK_PIN_NO(194) | 3)
+#define MT8135_PIN_194_SCL2__FUNC_PWM4 (MTK_PIN_NO(194) | 4)
+#define MT8135_PIN_194_SCL2__FUNC_TS_AUXADC_TEST_CK (MTK_PIN_NO(194) | 5)
+
+#define MT8135_PIN_195_SDA1__FUNC_GPIO195 (MTK_PIN_NO(195) | 0)
+#define MT8135_PIN_195_SDA1__FUNC_SDA1 (MTK_PIN_NO(195) | 1)
+#define MT8135_PIN_195_SDA1__FUNC_EINT93 (MTK_PIN_NO(195) | 2)
+#define MT8135_PIN_195_SDA1__FUNC_CLKM3 (MTK_PIN_NO(195) | 3)
+#define MT8135_PIN_195_SDA1__FUNC_PWM3 (MTK_PIN_NO(195) | 4)
+#define MT8135_PIN_195_SDA1__FUNC_TS_AUX_SCLK_PWDB (MTK_PIN_NO(195) | 5)
+
+#define MT8135_PIN_196_SCL1__FUNC_GPIO196 (MTK_PIN_NO(196) | 0)
+#define MT8135_PIN_196_SCL1__FUNC_SCL1 (MTK_PIN_NO(196) | 1)
+#define MT8135_PIN_196_SCL1__FUNC_EINT92 (MTK_PIN_NO(196) | 2)
+#define MT8135_PIN_196_SCL1__FUNC_CLKM2 (MTK_PIN_NO(196) | 3)
+#define MT8135_PIN_196_SCL1__FUNC_PWM2 (MTK_PIN_NO(196) | 4)
+#define MT8135_PIN_196_SCL1__FUNC_TS_AUX_DIN (MTK_PIN_NO(196) | 5)
+
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_GPIO197 (MTK_PIN_NO(197) | 0)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(197) | 1)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_EINT71 (MTK_PIN_NO(197) | 2)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_SCL6 (MTK_PIN_NO(197) | 3)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_PWM5 (MTK_PIN_NO(197) | 4)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_CLKM4 (MTK_PIN_NO(197) | 5)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MFG_TEST_CK_2 (MTK_PIN_NO(197) | 6)
+
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_GPIO198 (MTK_PIN_NO(198) | 0)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(198) | 1)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_EINT72 (MTK_PIN_NO(198) | 2)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_SDA6 (MTK_PIN_NO(198) | 3)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_PWM6 (MTK_PIN_NO(198) | 4)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_CLKM5 (MTK_PIN_NO(198) | 5)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MFG_TEST_CK_3 (MTK_PIN_NO(198) | 6)
+
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(199) | 1)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_EINT68 (MTK_PIN_NO(199) | 2)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_SDA2 (MTK_PIN_NO(199) | 3)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_PWM2 (MTK_PIN_NO(199) | 4)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_CLKM1 (MTK_PIN_NO(199) | 5)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_MFG_TEST_CK_4 (MTK_PIN_NO(199) | 6)
+
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(200) | 1)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_EINT67 (MTK_PIN_NO(200) | 2)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_SCL2 (MTK_PIN_NO(200) | 3)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_PWM1 (MTK_PIN_NO(200) | 4)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_CLKM0 (MTK_PIN_NO(200) | 5)
+
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(201) | 1)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_EINT70 (MTK_PIN_NO(201) | 2)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_SDA3 (MTK_PIN_NO(201) | 3)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_PWM4 (MTK_PIN_NO(201) | 4)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_CLKM3 (MTK_PIN_NO(201) | 5)
+
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_GPIO202 (MTK_PIN_NO(202) | 0)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(202) | 1)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_EINT69 (MTK_PIN_NO(202) | 2)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_SCL3 (MTK_PIN_NO(202) | 3)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_PWM3 (MTK_PIN_NO(202) | 4)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_CLKM2 (MTK_PIN_NO(202) | 5)
+
+#endif /* __DTS_MT8135_PINFUNC_H */
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 2c5c4da..d6c1f14 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -17,6 +17,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset-controller/mt8135-resets.h>
 #include "skeleton64.dtsi"
+#include "mt8135-pinfunc.h"
 
 / {
 	compatible = "mediatek,mt8135";
@@ -141,6 +142,36 @@
 			clock-names = "spi", "wrap";
 		};
 
+		/* Provide regmap for pinctrl driver */
+		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
+			compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
+			reg = <0 0x10005000 0 0x1000>;
+		};
+
+		/* Provide regmap for pinctrl driver */
+		syscfg_pctl_b: syscfg_pctl_b at 1020c000 {
+			compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
+			reg = <0 0x1020c000 0 0x1000>;
+		};
+
+		/*
+		 * Pinctrl access register at 0x10005000 and 0x1020c000 through
+		 * regmap. Register 0x1000b000 is used by EINT.
+		 */
+		pio: pinctrl at 10005000 {
+			compatible = "mediatek,mt8135-pinctrl";
+			reg = <0 0x1000b000 0 0x1000>;
+			mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
+			pins-are-numbered;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
 		timer: timer at 10008000 {
 			compatible = "mediatek,mt8135-timer",
 					"mediatek,mt6577-timer";
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:38 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:38 +0800
Subject: [PATCH v3 0/7] Add Mediatek MMC driver
Message-ID: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>

This series enables MMC support on the MT8135/MT8173 platform.
MT8135 has 5 MMC controllers and MT8173 has 4 MMC controllers.

Changes base on Ulf and Sascha's comments
Remove useless macros and use hex value
Remove setting for ocr_avail
Modify the flow of "set clock to 0"
Fix the race condition of cancel_delayed_work
Replace some dev_err to WARN_ON()
Remove useless "ACCESS_ONCE"	
Use clk_disable_unprepare() to instead of clk_disable() and clk_unprepare()
Use clk_prepare_enable() to instead  of clk_prepare() and clk_enable()
Fix the judgment of 1.8V IO
Fix the judgment of DDR mode
Make the enable/disable of vqmmc balanced
Fix runtime pm flow by Ulf and Sascha's comments


Chaotian Jing (3):
  mmc: dt-bindings: add Mediatek MMC bindings
  mmc: mediatek: Add Mediatek MMC driver
  mmc: mediatek: Add PM support for MMC driver

Eddie Huang (2):
  arm64: dts: mediatek: Add MT8173 MMC dts
  arm64: mediatek: Add Mediatek MMC support in defconfig

Yingjoe Chen (2):
  ARM: mediatek: dts: Add emmc support to mt8135
  ARM: multi_v7_defconfig: Enable Mediatek MMC support multi-v7

 Documentation/devicetree/bindings/mmc/mtk-sd.txt |   33 +
 arch/arm/boot/dts/mt8135-evbp1.dts               |  141 +++
 arch/arm/boot/dts/mt8135.dtsi                    |   26 +
 arch/arm/configs/multi_v7_defconfig              |    1 +
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts      |  115 ++
 arch/arm64/boot/dts/mediatek/mt8173.dtsi         |   22 +-
 arch/arm64/configs/defconfig                     |    1 +
 drivers/mmc/host/Kconfig                         |    8 +
 drivers/mmc/host/Makefile                        |    1 +
 drivers/mmc/host/mtk-sd.c                        | 1464 ++++++++++++++++++++++
 10 files changed, 1811 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt
 create mode 100644 drivers/mmc/host/mtk-sd.c




From chaotian.jing at mediatek.com  Tue Apr 28 02:48:39 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:39 +0800
Subject: [PATCH v3 1/7] mmc: dt-bindings: add Mediatek MMC bindings
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-2-git-send-email-chaotian.jing@mediatek.com>

Document the device-tree binding of Mediatek MMC host

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 Documentation/devicetree/bindings/mmc/mtk-sd.txt | 33 ++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt

diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
new file mode 100644
index 0000000..ba6d668
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
@@ -0,0 +1,33 @@
+* MTK MMC controller
+
+The MTK  MSDC can act as a MMC controller
+to support MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the msdc driver.
+
+Required properties:
+- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc".
+- interrupts: Should contain MSDC interrupt number
+- clocks: MSDC source clock, HCLK, HCLK is mandatory when it is not controlled by Infra
+- clock-names: "source", "hclk"
+- pinctrl-names: should be "default", "state_uhs"
+- pinctrl-0: should contain default/high speed pin ctrl
+- pinctrl-1: should contain uhs mode pin ctrl
+- vmmc-supply: power to the Core
+
+Optional properties:
+- vqmmc-supply: power to the IO(for SD/SDIO)
+
+Examples:
+mmc0: mmc at 11230000 {
+	compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
+	reg = <0 0x11230000 0 0x108>;
+	interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
+	vmmc-supply = <&mt6397_vemc_3v3_reg>;
+	clocks = <&pericfg CLK_PERI_MSDC30_0>, <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
+	clock-names = "source", "hclk";
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+};
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:41 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:41 +0800
Subject: [PATCH v3 3/7] mmc: mediatek: Add PM support for MMC driver
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-4-git-send-email-chaotian.jing@mediatek.com>

Add PM support for Mediatek MMC driver

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/host/mtk-sd.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 30e688d..79177d9 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -22,6 +22,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
 
@@ -215,6 +216,7 @@
 #define MSDC_ASYNC_FLAG (0x1 << 1)
 #define MSDC_MMAP_FLAG (0x1 << 2)
 
+#define MTK_MMC_AUTOSUSPEND_DELAY	500
 #define CMD_TIMEOUT         (HZ/10 * 5)	/* 100ms x5 */
 #define DAT_TIMEOUT         (HZ    * 5)	/* 1000ms x5 */
 
@@ -706,6 +708,9 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
 	if (mrq->data)
 		msdc_unprepare_data(host, mrq);
 	mmc_request_done(host->mmc, mrq);
+
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 }
 
 /* returns true if command is fully handled; returns false otherwise */
@@ -862,6 +867,8 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		WARN_ON(host->mrq);
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	pm_runtime_get_sync(host->dev);
+
 	if (mrq->data)
 		msdc_prepare_data(host, mrq);
 
@@ -999,7 +1006,6 @@ static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
 	int ret = 0;
 
 	if (!IS_ERR(mmc->supply.vqmmc)) {
-
 		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
 			min_uv = 3300000;
 			max_uv = 3300000;
@@ -1018,7 +1024,6 @@ static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
 					ret, min_uv, max_uv);
 		}
 	}
-
 	return ret;
 }
 
@@ -1176,8 +1181,10 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	int ret;
 	u32 ddr = 0;
 
+	pm_runtime_get_sync(host->dev);
+
 	if (ios->timing == MMC_TIMING_UHS_DDR50 ||
-		ios->timing == MMC_TIMING_MMC_DDR52)
+			ios->timing == MMC_TIMING_MMC_DDR52)
 		ddr = 1;
 
 	msdc_set_buswidth(host, ios->bus_width);
@@ -1191,7 +1198,7 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 					ios->vdd);
 			if (ret) {
 				dev_err(host->dev, "Failed to set vmmc power!\n");
-				return;
+				goto end;
 			}
 		}
 		break;
@@ -1227,6 +1234,10 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	if (host->mclk != ios->clock || host->ddr != ddr)
 		msdc_set_mclk(host, ddr, ios->clock);
+
+end:
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 }
 
 static struct mmc_host_ops mt_msdc_ops = {
@@ -1350,12 +1361,19 @@ static int msdc_drv_probe(struct platform_device *pdev)
 	if (ret)
 		goto release;
 
+	pm_runtime_set_active(host->dev);
+	pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(host->dev);
+	pm_runtime_enable(host->dev);
 	ret = mmc_add_host(mmc);
+
 	if (ret)
-		goto release;
+		goto end;
 
 	return 0;
 
+end:
+	pm_runtime_disable(host->dev);
 release:
 	platform_set_drvdata(pdev, NULL);
 	msdc_deinit_hw(host);
@@ -1368,6 +1386,7 @@ release_mem:
 		dma_free_coherent(&pdev->dev,
 			MAX_BD_NUM * sizeof(struct mt_bdma_desc),
 			host->dma.bd, host->dma.bd_addr);
+
 host_free:
 	mmc_free_host(mmc);
 
@@ -1382,10 +1401,14 @@ static int msdc_drv_remove(struct platform_device *pdev)
 	mmc = platform_get_drvdata(pdev);
 	host = mmc_priv(mmc);
 
+	pm_runtime_get_sync(host->dev);
+
 	platform_set_drvdata(pdev, NULL);
 	mmc_remove_host(host->mmc);
 	msdc_deinit_hw(host);
 
+	pm_runtime_disable(host->dev);
+	pm_runtime_put_noidle(host->dev);
 	dma_free_coherent(&pdev->dev,
 			sizeof(struct mt_gpdma_desc),
 			host->dma.gpd, host->dma.gpd_addr);
@@ -1397,6 +1420,30 @@ static int msdc_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int msdc_runtime_suspend(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msdc_host *host = mmc_priv(mmc);
+
+	msdc_gate_clock(host);
+	return 0;
+}
+
+static int msdc_runtime_resume(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msdc_host *host = mmc_priv(mmc);
+
+	msdc_ungate_clock(host);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops msdc_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL)
+};
+
 static const struct of_device_id msdc_of_ids[] = {
 	{   .compatible = "mediatek,mt8135-mmc", },
 	{}
@@ -1408,6 +1455,7 @@ static struct platform_driver mt_msdc_driver = {
 	.driver = {
 		.name = "mtk-msdc",
 		.of_match_table = msdc_of_ids,
+		.pm = &msdc_dev_pm_ops,
 	},
 };
 
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:40 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:40 +0800
Subject: [PATCH v3 2/7] mmc: mediatek: Add Mediatek MMC driver
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-3-git-send-email-chaotian.jing@mediatek.com>

Add Mediatek MMC driver code
Support eMMC/SD/SDIO

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/host/Kconfig  |    8 +
 drivers/mmc/host/Makefile |    1 +
 drivers/mmc/host/mtk-sd.c | 1416 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1425 insertions(+)
 create mode 100644 drivers/mmc/host/mtk-sd.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index b1f837e..6c3dbb9 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -775,3 +775,11 @@ config MMC_TOSHIBA_PCI
 	tristate "Toshiba Type A SD/MMC Card Interface Driver"
 	depends on PCI
 	help
+
+config MMC_MTK
+	tristate "MediaTek SD/MMC Card Interface support"
+	help
+	  This selects the MediaTek(R) Secure digital and Multimedia card Interface.
+	  If you have a machine with a integrated SD/MMC card reader, say Y or M here.
+	  This is needed if support for any SD/SDIO/MMC devices is required.
+	  If unsure, say N.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e3ab5b9..7473b79 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30)	+= sdhci_f_sdh30.o
 obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
+obj-$(CONFIG_MMC_MTK)           += mtk-sd.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
 obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
new file mode 100644
index 0000000..30e688d
--- /dev/null
+++ b/drivers/mmc/host/mtk-sd.c
@@ -0,0 +1,1416 @@
+/*
+ * Copyright (c) 2014-2015 MediaTek Inc.
+ * Author: Chaotian.Jing <chaotian.jing at mediatek.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spinlock.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sdio.h>
+
+#define MAX_BD_NUM          1024
+
+/*--------------------------------------------------------------------------*/
+/* Common Definition                                                        */
+/*--------------------------------------------------------------------------*/
+#define MSDC_MS                 0x0
+#define MSDC_SDMMC              0x1
+
+#define MSDC_BUS_1BITS          0x0
+#define MSDC_BUS_4BITS          0x1
+#define MSDC_BUS_8BITS          0x2
+
+#define MSDC_BURST_64B          0x6
+
+/*--------------------------------------------------------------------------*/
+/* Register Offset                                                          */
+/*--------------------------------------------------------------------------*/
+#define MSDC_CFG         0x0
+#define MSDC_IOCON       0x04
+#define MSDC_PS          0x08
+#define MSDC_INT         0x0c
+#define MSDC_INTEN       0x10
+#define MSDC_FIFOCS      0x14
+#define SDC_CFG          0x30
+#define SDC_CMD          0x34
+#define SDC_ARG          0x38
+#define SDC_STS          0x3c
+#define SDC_RESP0        0x40
+#define SDC_RESP1        0x44
+#define SDC_RESP2        0x48
+#define SDC_RESP3        0x4c
+#define SDC_BLK_NUM      0x50
+#define SDC_ACMD_RESP    0x80
+#define MSDC_DMA_SA      0x90
+#define MSDC_DMA_CTRL    0x98
+#define MSDC_DMA_CFG     0x9c
+#define MSDC_PATCH_BIT   0xb0
+#define MSDC_PATCH_BIT1  0xb4
+#define MSDC_PAD_TUNE    0xec
+
+/*--------------------------------------------------------------------------*/
+/* Register Mask                                                            */
+/*--------------------------------------------------------------------------*/
+
+/* MSDC_CFG mask */
+#define MSDC_CFG_MODE           (0x1 << 0)	/* RW */
+#define MSDC_CFG_CKPDN          (0x1 << 1)	/* RW */
+#define MSDC_CFG_RST            (0x1 << 2)	/* RW */
+#define MSDC_CFG_PIO            (0x1 << 3)	/* RW */
+#define MSDC_CFG_CKDRVEN        (0x1 << 4)	/* RW */
+#define MSDC_CFG_BV18SDT        (0x1 << 5)	/* RW */
+#define MSDC_CFG_BV18PSS        (0x1 << 6)	/* R  */
+#define MSDC_CFG_CKSTB          (0x1 << 7)	/* R  */
+#define MSDC_CFG_CKDIV          (0xff << 8)	/* RW */
+#define MSDC_CFG_CKMOD          (0x3 << 16)	/* RW */
+
+/* MSDC_IOCON mask */
+#define MSDC_IOCON_SDR104CKS    (0x1 << 0)	/* RW */
+#define MSDC_IOCON_RSPL         (0x1 << 1)	/* RW */
+#define MSDC_IOCON_DSPL         (0x1 << 2)	/* RW */
+#define MSDC_IOCON_DDLSEL       (0x1 << 3)	/* RW */
+#define MSDC_IOCON_DDR50CKD     (0x1 << 4)	/* RW */
+#define MSDC_IOCON_DSPLSEL      (0x1 << 5)	/* RW */
+#define MSDC_IOCON_W_DSPL       (0x1 << 8)	/* RW */
+#define MSDC_IOCON_D0SPL        (0x1 << 16)	/* RW */
+#define MSDC_IOCON_D1SPL        (0x1 << 17)	/* RW */
+#define MSDC_IOCON_D2SPL        (0x1 << 18)	/* RW */
+#define MSDC_IOCON_D3SPL        (0x1 << 19)	/* RW */
+#define MSDC_IOCON_D4SPL        (0x1 << 20)	/* RW */
+#define MSDC_IOCON_D5SPL        (0x1 << 21)	/* RW */
+#define MSDC_IOCON_D6SPL        (0x1 << 22)	/* RW */
+#define MSDC_IOCON_D7SPL        (0x1 << 23)	/* RW */
+#define MSDC_IOCON_RISCSZ       (0x3 << 24)	/* RW */
+
+/* MSDC_PS mask */
+#define MSDC_PS_CDEN            (0x1 << 0)	/* RW */
+#define MSDC_PS_CDSTS           (0x1 << 1)	/* R  */
+#define MSDC_PS_CDDEBOUNCE      (0xf << 12)	/* RW */
+#define MSDC_PS_DAT             (0xff << 16)	/* R  */
+#define MSDC_PS_CMD             (0x1 << 24)	/* R  */
+#define MSDC_PS_WP              (0x1 << 31)	/* R  */
+
+/* MSDC_INT mask */
+#define MSDC_INT_MMCIRQ         (0x1 << 0)	/* W1C */
+#define MSDC_INT_CDSC           (0x1 << 1)	/* W1C */
+#define MSDC_INT_ACMDRDY        (0x1 << 3)	/* W1C */
+#define MSDC_INT_ACMDTMO        (0x1 << 4)	/* W1C */
+#define MSDC_INT_ACMDCRCERR     (0x1 << 5)	/* W1C */
+#define MSDC_INT_DMAQ_EMPTY     (0x1 << 6)	/* W1C */
+#define MSDC_INT_SDIOIRQ        (0x1 << 7)	/* W1C */
+#define MSDC_INT_CMDRDY         (0x1 << 8)	/* W1C */
+#define MSDC_INT_CMDTMO         (0x1 << 9)	/* W1C */
+#define MSDC_INT_RSPCRCERR      (0x1 << 10)	/* W1C */
+#define MSDC_INT_CSTA           (0x1 << 11)	/* R */
+#define MSDC_INT_XFER_COMPL     (0x1 << 12)	/* W1C */
+#define MSDC_INT_DXFER_DONE     (0x1 << 13)	/* W1C */
+#define MSDC_INT_DATTMO         (0x1 << 14)	/* W1C */
+#define MSDC_INT_DATCRCERR      (0x1 << 15)	/* W1C */
+#define MSDC_INT_ACMD19_DONE    (0x1 << 16)	/* W1C */
+#define MSDC_INT_DMA_BDCSERR    (0x1 << 17)	/* W1C */
+#define MSDC_INT_DMA_GPDCSERR   (0x1 << 18)	/* W1C */
+#define MSDC_INT_DMA_PROTECT    (0x1 << 19)	/* W1C */
+
+/* MSDC_INTEN mask */
+#define MSDC_INTEN_MMCIRQ       (0x1 << 0)	/* RW */
+#define MSDC_INTEN_CDSC         (0x1 << 1)	/* RW */
+#define MSDC_INTEN_ACMDRDY      (0x1 << 3)	/* RW */
+#define MSDC_INTEN_ACMDTMO      (0x1 << 4)	/* RW */
+#define MSDC_INTEN_ACMDCRCERR   (0x1 << 5)	/* RW */
+#define MSDC_INTEN_DMAQ_EMPTY   (0x1 << 6)	/* RW */
+#define MSDC_INTEN_SDIOIRQ      (0x1 << 7)	/* RW */
+#define MSDC_INTEN_CMDRDY       (0x1 << 8)	/* RW */
+#define MSDC_INTEN_CMDTMO       (0x1 << 9)	/* RW */
+#define MSDC_INTEN_RSPCRCERR    (0x1 << 10)	/* RW */
+#define MSDC_INTEN_CSTA         (0x1 << 11)	/* RW */
+#define MSDC_INTEN_XFER_COMPL   (0x1 << 12)	/* RW */
+#define MSDC_INTEN_DXFER_DONE   (0x1 << 13)	/* RW */
+#define MSDC_INTEN_DATTMO       (0x1 << 14)	/* RW */
+#define MSDC_INTEN_DATCRCERR    (0x1 << 15)	/* RW */
+#define MSDC_INTEN_ACMD19_DONE  (0x1 << 16)	/* RW */
+#define MSDC_INTEN_DMA_BDCSERR  (0x1 << 17)	/* RW */
+#define MSDC_INTEN_DMA_GPDCSERR (0x1 << 18)	/* RW */
+#define MSDC_INTEN_DMA_PROTECT  (0x1 << 19)	/* RW */
+
+/* MSDC_FIFOCS mask */
+#define MSDC_FIFOCS_RXCNT       (0xff << 0)	/* R */
+#define MSDC_FIFOCS_TXCNT       (0xff << 16)	/* R */
+#define MSDC_FIFOCS_CLR         (0x1 << 31)	/* RW */
+
+/* SDC_CFG mask */
+#define SDC_CFG_SDIOINTWKUP     (0x1 << 0)	/* RW */
+#define SDC_CFG_INSWKUP         (0x1 << 1)	/* RW */
+#define SDC_CFG_BUSWIDTH        (0x3 << 16)	/* RW */
+#define SDC_CFG_SDIO            (0x1 << 19)	/* RW */
+#define SDC_CFG_SDIOIDE         (0x1 << 20)	/* RW */
+#define SDC_CFG_INTATGAP        (0x1 << 21)	/* RW */
+#define SDC_CFG_DTOC            (0xff << 24)	/* RW */
+
+/* SDC_STS mask */
+#define SDC_STS_SDCBUSY         (0x1 << 0)	/* RW */
+#define SDC_STS_CMDBUSY         (0x1 << 1)	/* RW */
+#define SDC_STS_SWR_COMPL       (0x1 << 31)	/* RW */
+
+/* MSDC_DMA_CTRL mask */
+#define MSDC_DMA_CTRL_START     (0x1 << 0)	/* W */
+#define MSDC_DMA_CTRL_STOP      (0x1 << 1)	/* W */
+#define MSDC_DMA_CTRL_RESUME    (0x1 << 2)	/* W */
+#define MSDC_DMA_CTRL_MODE      (0x1 << 8)	/* RW */
+#define MSDC_DMA_CTRL_LASTBUF   (0x1 << 10)	/* RW */
+#define MSDC_DMA_CTRL_BRUSTSZ   (0x7 << 12)	/* RW */
+
+/* MSDC_DMA_CFG mask */
+#define MSDC_DMA_CFG_STS        (0x1 << 0)	/* R */
+#define MSDC_DMA_CFG_DECSEN     (0x1 << 1)	/* RW */
+#define MSDC_DMA_CFG_AHBHPROT2  (0x2 << 8)	/* RW */
+#define MSDC_DMA_CFG_ACTIVEEN   (0x2 << 12)	/* RW */
+#define MSDC_DMA_CFG_CS12B16B   (0x1 << 16)	/* RW */
+
+/* MSDC_PATCH_BIT mask */
+#define MSDC_PATCH_BIT_ODDSUPP    (0x1 <<  1)	/* RW */
+#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 <<  7)
+#define MSDC_CKGEN_MSDC_DLY_SEL   (0x1f << 10)
+#define MSDC_PATCH_BIT_IODSSEL    (0x1 << 16)	/* RW */
+#define MSDC_PATCH_BIT_IOINTSEL   (0x1 << 17)	/* RW */
+#define MSDC_PATCH_BIT_BUSYDLY    (0xf << 18)	/* RW */
+#define MSDC_PATCH_BIT_WDOD       (0xf << 22)	/* RW */
+#define MSDC_PATCH_BIT_IDRTSEL    (0x1 << 26)	/* RW */
+#define MSDC_PATCH_BIT_CMDFSEL    (0x1 << 27)	/* RW */
+#define MSDC_PATCH_BIT_INTDLSEL   (0x1 << 28)	/* RW */
+#define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29)	/* RW */
+#define MSDC_PATCH_BIT_DECRCTMO   (0x1 << 30)	/* RW */
+
+#define REQ_CMD_EIO  (0x1 << 0)
+#define REQ_CMD_TMO  (0x1 << 1)
+#define REQ_DAT_ERR  (0x1 << 2)
+#define REQ_STOP_EIO (0x1 << 3)
+#define REQ_STOP_TMO (0x1 << 4)
+#define REQ_CMD_BUSY (0x1 << 5)
+
+#define MSDC_PREPARE_FLAG (0x1 << 0)
+#define MSDC_ASYNC_FLAG (0x1 << 1)
+#define MSDC_MMAP_FLAG (0x1 << 2)
+
+#define CMD_TIMEOUT         (HZ/10 * 5)	/* 100ms x5 */
+#define DAT_TIMEOUT         (HZ    * 5)	/* 1000ms x5 */
+
+/*--------------------------------------------------------------------------*/
+/* Descriptor Structure                                                     */
+/*--------------------------------------------------------------------------*/
+struct mt_gpdma_desc {
+	u32 first_u32;
+#define GPDMA_DESC_HWO		(0x1 << 0)
+#define GPDMA_DESC_BDP		(0x1 << 1)
+#define GPDMA_DESC_CHECKSUM	(0xff << 8) /* bit8 ~ bit15 */
+#define GPDMA_DESC_INT		(0x1 << 16)
+	u32 next;
+	u32 ptr;
+	u32 second_u32;
+#define GPDMA_DESC_BUFLEN	(0xffff) /* bit0 ~ bit15 */
+#define GPDMA_DESC_EXTLEN	(0xff << 16) /* bit16 ~ bit23 */
+	u32 arg;
+	u32 blknum;
+	u32 cmd;
+};
+
+struct mt_bdma_desc {
+	u32 first_u32;
+#define BDMA_DESC_EOL		(0x1 << 0)
+#define BDMA_DESC_CHECKSUM	(0xff << 8) /* bit8 ~ bit15 */
+#define BDMA_DESC_BLKPAD	(0x1 << 17)
+#define BDMA_DESC_DWPAD		(0x1 << 18)
+	u32 next;
+	u32 ptr;
+	u32 second_u32;
+#define BDMA_DESC_BUFLEN	(0xffff) /* bit0 ~ bit15 */
+};
+
+struct msdc_dma {
+	struct scatterlist *sg;	/* I/O scatter list */
+	struct mt_gpdma_desc *gpd;		/* pointer to gpd array */
+	struct mt_bdma_desc *bd;		/* pointer to bd array */
+	dma_addr_t gpd_addr;	/* the physical address of gpd array */
+	dma_addr_t bd_addr;	/* the physical address of bd array */
+};
+
+struct msdc_host {
+	struct device *dev;
+	struct mmc_host *mmc;	/* mmc structure */
+	int cmd_rsp;
+
+	spinlock_t lock;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+	int error;
+
+	void __iomem *base;		/* host base address */
+
+	struct msdc_dma dma;	/* dma channel */
+
+	u32 timeout_ns;		/* data timeout ns */
+	u32 timeout_clks;	/* data timeout clks */
+
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_default;
+	struct pinctrl_state *pins_uhs;
+	struct delayed_work req_timeout;
+	int irq;		/* host interrupt */
+
+	struct clk *src_clk;	/* msdc source clock */
+	struct clk *h_clk;      /* msdc h_clk */
+	u32 mclk;		/* mmc subsystem clock */
+	u32 hclk;		/* host clock speed */
+	u32 sclk;		/* SD/MS clock speed */
+	bool ddr;
+	bool vqmmc_enabled;
+	bool sclk_enabled;	/* source clock enabled */
+};
+
+static void sdr_set_bits(void __iomem *reg, u32 bs)
+{
+	u32 val = readl(reg);
+
+	val |= bs;
+	writel(val, reg);
+}
+
+static void sdr_clr_bits(void __iomem *reg, u32 bs)
+{
+	u32 val = readl(reg);
+
+	val &= ~(u32)bs;
+	writel(val, reg);
+}
+
+static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
+{
+	unsigned int tv = readl(reg);
+
+	tv &= ~field;
+	tv |= ((val) << (ffs((unsigned int)field) - 1));
+	writel(tv, reg);
+}
+
+static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
+{
+	unsigned int tv = readl(reg);
+
+	*val = ((tv & field) >> (ffs((unsigned int)field) - 1));
+}
+
+static void msdc_reset_hw(struct msdc_host *host)
+{
+	u32 val;
+
+	sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
+	while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
+		cpu_relax();
+
+	sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
+	while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
+		cpu_relax();
+
+	val = readl(host->base + MSDC_INT);
+	writel(val, host->base + MSDC_INT);
+}
+
+static void msdc_cmd_next(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd);
+
+static u32 data_ints_mask = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO |
+			MSDC_INTEN_DATCRCERR | MSDC_INTEN_DMA_BDCSERR |
+			MSDC_INTEN_DMA_GPDCSERR | MSDC_INTEN_DMA_PROTECT;
+
+static u8 msdc_dma_calcs(u8 *buf, u32 len)
+{
+	u32 i, sum = 0;
+
+	for (i = 0; i < len; i++)
+		sum += buf[i];
+	return 0xff - (u8) sum;
+}
+
+static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
+		struct mmc_data *data)
+{
+	u32 sglen, j;
+	u32 dma_address, dma_len;
+	struct scatterlist *sg;
+	struct mt_gpdma_desc *gpd;
+	struct mt_bdma_desc *bd;
+
+	sglen = data->sg_len;
+	sg = data->sg;
+
+	gpd = dma->gpd;
+	bd = dma->bd;
+
+	/* modify gpd */
+	gpd->first_u32 |= GPDMA_DESC_HWO;
+	gpd->first_u32 |= GPDMA_DESC_BDP;
+	/* need to clear first. use these bits to calc checksum */
+	gpd->first_u32 &= ~GPDMA_DESC_CHECKSUM;
+	gpd->first_u32 |= msdc_dma_calcs((u8 *) gpd, 16) << 8;
+
+	/* modify bd */
+	for (j = 0; j < sglen; j++) {
+		dma_address = sg_dma_address(sg);
+		dma_len = sg_dma_len(sg);
+
+		/* init bd */
+		bd[j].first_u32 &= ~BDMA_DESC_BLKPAD;
+		bd[j].first_u32 &= ~BDMA_DESC_DWPAD;
+		bd[j].ptr = (u32)dma_address;
+		bd[j].second_u32 &= ~BDMA_DESC_BUFLEN;
+		bd[j].second_u32 |= (dma_len & BDMA_DESC_BUFLEN);
+
+		if (j == sglen - 1) /* the last bd */
+			bd[j].first_u32 |= BDMA_DESC_EOL;
+		else
+			bd[j].first_u32 &= ~BDMA_DESC_EOL;
+
+		/* checksume need to clear first */
+		bd[j].first_u32 &= ~BDMA_DESC_CHECKSUM;
+		bd[j].first_u32 |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8;
+		sg++;
+	}
+
+	sdr_set_field(host->base + MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1);
+	sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ,
+			MSDC_BURST_64B);
+	sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1);
+
+	writel((u32)dma->gpd_addr, host->base + MSDC_DMA_SA);
+}
+
+static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
+{
+	struct mmc_data *data = mrq->data;
+
+	if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
+		bool read = (data->flags & MMC_DATA_READ) != 0;
+
+		data->host_cookie |= MSDC_PREPARE_FLAG;
+		dma_map_sg(host->dev, data->sg, data->sg_len,
+			   read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+	}
+}
+
+static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
+{
+	struct mmc_data *data = mrq->data;
+
+	if (data->host_cookie & MSDC_ASYNC_FLAG)
+		return;
+
+	if ((data->host_cookie & MSDC_PREPARE_FLAG)) {
+		bool read = (data->flags & MMC_DATA_READ) != 0;
+
+		dma_unmap_sg(host->dev, data->sg, data->sg_len,
+			     read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+		data->host_cookie &= ~MSDC_PREPARE_FLAG;
+	}
+}
+
+/* clock control primitives */
+static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
+{
+	u32 timeout, clk_ns;
+	u32 mode = 0;
+
+	host->timeout_ns = ns;
+	host->timeout_clks = clks;
+	if (host->sclk == 0) {
+		timeout = 0;
+	} else {
+		clk_ns  = 1000000000UL / host->sclk;
+		timeout = (ns + clk_ns - 1) / clk_ns + clks;
+		/* in 1048576 sclk cycle unit */
+		timeout = (timeout + (0x1 << 20) - 1) >> 20;
+		sdr_get_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, &mode);
+		/*DDR mode will double the clk cycles for data timeout */
+		timeout = mode >= 2 ? timeout * 2 : timeout;
+		timeout = timeout > 1 ? timeout - 1 : 0;
+		timeout = timeout > 255 ? 255 : timeout;
+	}
+	sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
+}
+
+static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
+{
+	u32 mode;
+	u32 flags;
+	u32 div;
+	u32 sclk;
+	u32 hclk = host->hclk;
+
+	if (!hz) {
+		dev_dbg(host->dev, "set mclk to 0\n");
+		host->mclk = 0;
+		sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_MS);
+		return;
+	}
+
+	flags = readl(host->base + MSDC_INTEN);
+	sdr_clr_bits(host->base + MSDC_INTEN, flags);
+
+	if (ddr) { /* may need to modify later */
+		mode = 0x2; /* ddr mode and use divisor */
+		if (hz >= (hclk >> 2)) {
+			div = 0; /* mean div = 1/4 */
+			sclk = hclk >> 2; /* sclk = clk / 4 */
+		} else {
+			div = (hclk + ((hz << 2) - 1)) / (hz << 2);
+			sclk = (hclk >> 2) / div;
+			div = (div >> 1);
+		}
+	} else if (hz >= hclk) {
+		mode = 0x1; /* no divisor */
+		div = 0;
+		sclk = hclk;
+	} else {
+		mode = 0x0; /* use divisor */
+		if (hz >= (hclk >> 1)) {
+			div = 0; /* mean div = 1/2 */
+			sclk = hclk >> 1; /* sclk = clk / 2 */
+		} else {
+			div = (hclk + ((hz << 2) - 1)) / (hz << 2);
+			sclk = (hclk >> 2) / div;
+		}
+	}
+
+	sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
+			(mode << 8) | (div % 0xff));
+	while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
+		cpu_relax();
+
+	host->sclk = sclk;
+	host->mclk = hz;
+	host->ddr = ddr;
+	/* need because clk changed. */
+	msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
+	sdr_set_bits(host->base + MSDC_INTEN, flags);
+
+	dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);
+}
+
+static void msdc_gate_clock(struct msdc_host *host)
+{
+	/* disable SD/MMC/SDIO bus clock */
+	sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_MS);
+	/* turn off SDHC functional clock */
+	if (host->sclk_enabled) {
+		clk_disable_unprepare(host->src_clk);
+		host->sclk_enabled = false;
+	}
+}
+
+static void msdc_ungate_clock(struct msdc_host *host)
+{
+	if (!host->sclk_enabled) {
+		clk_prepare_enable(host->src_clk);
+		host->sclk_enabled = true;
+	}
+	/* enable SD/MMC/SDIO bus clock:
+	 * it will be automatically gated when the bus is idle
+	 * (set MSDC_CFG_CKPDN bit to have it always on)
+	 */
+	sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC);
+	while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
+		cpu_relax();
+}
+
+static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	u32 resp;
+
+	switch (mmc_resp_type(cmd)) {
+		/* Actually, R1, R5, R6, R7 are the same */
+	case MMC_RSP_R1:
+		resp = 0x1;
+		break;
+	case MMC_RSP_R1B:
+		resp = 0x7;
+		break;
+	case MMC_RSP_R2:
+		resp = 0x2;
+		break;
+	case MMC_RSP_R3:
+		resp = 0x3;
+		break;
+	case MMC_RSP_NONE:
+	default:
+		resp = 0x0;
+		break;
+	}
+
+	return resp;
+}
+
+static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	/* rawcmd :
+	 * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
+	 * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
+	 */
+	u32 opcode = cmd->opcode;
+	u32 resp = msdc_cmd_find_resp(host, mrq, cmd);
+	u32 rawcmd = (opcode & 0x3f) | ((resp & 0x7) << 7);
+
+	host->cmd_rsp = resp;
+
+	if ((opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int) -1) ||
+			opcode == MMC_STOP_TRANSMISSION)
+		rawcmd |= (0x1 << 14);
+	else if (opcode == SD_SWITCH_VOLTAGE)
+		rawcmd |= (0x1 << 30);
+	else if ((opcode == SD_APP_SEND_SCR) ||
+			(opcode == SD_APP_SEND_NUM_WR_BLKS) ||
+			(opcode == SD_SWITCH &&
+			(mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
+			(opcode == SD_APP_SD_STATUS &&
+			(mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
+			(opcode == MMC_SEND_EXT_CSD &&
+			(mmc_cmd_type(cmd) == MMC_CMD_ADTC)))
+		rawcmd |= (0x1 << 11);
+
+	if (cmd->data) {
+		struct mmc_data *data = cmd->data;
+
+		if (mmc_op_multi(opcode)) {
+			if (mmc_card_mmc(host->mmc->card) && mrq->sbc &&
+					!(mrq->sbc->arg & 0xFFFF0000))
+				rawcmd |= 0x2 << 28; /* AutoCMD23 */
+		}
+
+		rawcmd |= ((data->blksz & 0xFFF) << 16);
+		if (data->flags & MMC_DATA_WRITE)
+			rawcmd |= (0x1 << 13);
+		if (data->blocks > 1)
+			rawcmd |= (0x2 << 11);
+		else
+			rawcmd |= (0x1 << 11);
+		/* Always use dma mode */
+		sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO);
+
+		if (((host->timeout_ns != data->timeout_ns) ||
+				(host->timeout_clks != data->timeout_clks))) {
+			msdc_set_timeout(host, data->timeout_ns,
+					data->timeout_clks);
+		}
+
+		writel(data->blocks, host->base + SDC_BLK_NUM);
+	}
+	return rawcmd;
+}
+
+static void msdc_start_data(struct msdc_host *host, struct mmc_request *mrq,
+			    struct mmc_command *cmd, struct mmc_data *data)
+{
+	bool read;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->data)
+		host->data = data;
+	else
+		WARN_ON(host->data);
+	spin_unlock_irqrestore(&host->lock, flags);
+	read = data->flags & MMC_DATA_READ;
+
+	mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
+	msdc_dma_setup(host, &host->dma, data);
+	sdr_set_bits(host->base + MSDC_INTEN, data_ints_mask);
+	mb(); /* wait for pending IO to finish */
+	sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
+	dev_dbg(host->dev, "DMA start\n");
+	dev_dbg(host->dev, "%s: cmd=%d DMA data: %d blocks; read=%d\n",
+			__func__, cmd->opcode, data->blocks, read);
+}
+
+static int msdc_auto_cmd_done(struct msdc_host *host, int events,
+		struct mmc_command *cmd)
+{
+	u32 *rsp = cmd->resp;
+
+	rsp[0] = readl(host->base + SDC_ACMD_RESP);
+
+	if (events & MSDC_INT_ACMDRDY) {
+		cmd->error = 0;
+	} else {
+		msdc_reset_hw(host);
+		if (events & MSDC_INT_ACMDCRCERR) {
+			cmd->error = -EILSEQ;
+			host->error |= REQ_STOP_EIO;
+		} else if (events & MSDC_INT_ACMDTMO) {
+			cmd->error = -ETIMEDOUT;
+			host->error |= REQ_STOP_TMO;
+		}
+		dev_err(host->dev,
+			"%s: AUTO_CMD%d arg=%08X; rsp %08X; cmd_error=%d\n",
+			__func__, cmd->opcode, cmd->arg, rsp[0], cmd->error);
+	}
+	return cmd->error;
+}
+
+static void msdc_track_cmd_data(struct msdc_host *host,
+				struct mmc_command *cmd, struct mmc_data *data)
+{
+	if (host->error)
+		dev_dbg(host->dev, "%s: cmd=%d arg=%08X; host->error=0x%08X\n",
+			__func__, cmd->opcode, cmd->arg, host->error);
+}
+
+static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
+{
+	unsigned long flags;
+	bool ret;
+
+	ret = cancel_delayed_work(&host->req_timeout);
+	if (!ret) {
+		/* delay work already running */
+		return;
+	}
+	spin_lock_irqsave(&host->lock, flags);
+	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	msdc_track_cmd_data(host, mrq->cmd, mrq->data);
+	if (mrq->data)
+		msdc_unprepare_data(host, mrq);
+	mmc_request_done(host->mmc, mrq);
+}
+
+/* returns true if command is fully handled; returns false otherwise */
+static bool msdc_cmd_done(struct msdc_host *host, int events,
+			  struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	bool done = false;
+	bool sbc_error;
+	unsigned long flags;
+	u32 *rsp = cmd->resp;
+
+	if (mrq->sbc && cmd == mrq->cmd &&
+			(events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR
+				   | MSDC_INT_ACMDTMO)))
+		msdc_auto_cmd_done(host, events, mrq->sbc);
+
+	sbc_error = mrq->sbc && mrq->sbc->error;
+
+	if (!sbc_error && !(events & (MSDC_INT_CMDRDY
+					| MSDC_INT_RSPCRCERR
+					| MSDC_INT_CMDTMO)))
+		return done;
+
+	spin_lock_irqsave(&host->lock, flags);
+	done = !host->cmd;
+	host->cmd = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (done)
+		return true;
+
+	sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
+			MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
+			MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
+			MSDC_INTEN_ACMDTMO);
+	writel(cmd->arg, host->base + SDC_ARG);
+
+	switch (host->cmd_rsp) {
+	case 0:
+		break;
+	case 2:
+		rsp[0] = readl(host->base + SDC_RESP3);
+		rsp[1] = readl(host->base + SDC_RESP2);
+		rsp[2] = readl(host->base + SDC_RESP1);
+		rsp[3] = readl(host->base + SDC_RESP0);
+		break;
+	default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
+		rsp[0] = readl(host->base + SDC_RESP0);
+		break;
+	}
+	if (!sbc_error && !(events & MSDC_INT_CMDRDY)) {
+		msdc_reset_hw(host);
+		if (events & MSDC_INT_RSPCRCERR) {
+			cmd->error = -EILSEQ;
+			host->error |= REQ_CMD_EIO;
+		} else if (events & MSDC_INT_CMDTMO) {
+			cmd->error = -ETIMEDOUT;
+			host->error |= REQ_CMD_TMO;
+		}
+	}
+	if (cmd->error)
+		dev_dbg(host->dev,
+				"%s: cmd=%d arg=%08X; rsp %08X; cmd_error=%d\n",
+				__func__, cmd->opcode, cmd->arg, rsp[0],
+				cmd->error);
+
+	msdc_cmd_next(host, mrq, cmd);
+	done = true;
+	return done;
+}
+
+static inline bool msdc_cmd_is_ready(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	unsigned long tmo = jiffies + msecs_to_jiffies(20);
+
+	while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY)
+			&& time_before(jiffies, tmo))
+		continue;
+
+	if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
+		dev_err(host->dev, "CMD bus busy detected\n");
+		host->error |= REQ_CMD_BUSY;
+		msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
+		return false;
+	}
+
+	if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
+		/* R1B or with data, should check SDCBUSY */
+		while (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY)
+			cpu_relax();
+	}
+	return true;
+}
+
+static void msdc_start_command(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	u32 rawcmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->cmd)
+		WARN_ON(host->cmd);
+	else
+		host->cmd = cmd;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (!msdc_cmd_is_ready(host, mrq, cmd))
+		return;
+
+	if ((readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16
+		|| (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT)) {
+		dev_err(host->dev, "TX/RX FIFO non-empty before start of IO. Reset\n");
+		msdc_reset_hw(host);
+	}
+
+	cmd->error = 0;
+	rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
+	mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
+
+	sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
+			MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
+			MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
+			MSDC_INTEN_ACMDTMO);
+	writel(cmd->arg, host->base + SDC_ARG);
+	writel(rawcmd, host->base + SDC_CMD);
+}
+
+static void msdc_cmd_next(struct msdc_host *host,
+		struct mmc_request *mrq, struct mmc_command *cmd)
+{
+	if (cmd->error || (mrq->sbc && mrq->sbc->error))
+		msdc_request_done(host, mrq);
+	else if (cmd == mrq->sbc)
+		msdc_start_command(host, mrq, mrq->cmd);
+	else if (!cmd->data)
+		msdc_request_done(host, mrq);
+	else
+		msdc_start_data(host, mrq, cmd, cmd->data);
+}
+
+static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	unsigned long flags;
+	struct msdc_host *host = mmc_priv(mmc);
+
+	host->error = 0;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->mrq)
+		host->mrq = mrq;
+	else
+		WARN_ON(host->mrq);
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (mrq->data)
+		msdc_prepare_data(host, mrq);
+
+	/* if SBC is required, we have HW option and SW option.
+	 * if HW option is enabled, and SBC does not have "special" flags,
+	 * use HW option,  otherwise use SW option
+	 */
+	if (mrq->sbc && (!mmc_card_mmc(mmc->card) ||
+	    (mrq->sbc->arg & 0xFFFF0000)))
+		msdc_start_command(host, mrq, mrq->sbc);
+	else
+		msdc_start_command(host, mrq, mrq->cmd);
+}
+
+static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		bool is_first_req)
+{
+	struct msdc_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (!data)
+		return;
+
+	msdc_prepare_data(host, mrq);
+	data->host_cookie |= MSDC_ASYNC_FLAG;
+}
+
+static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		int err)
+{
+	struct msdc_host *host = mmc_priv(mmc);
+	struct mmc_data *data;
+
+	data = mrq->data;
+	if (!data)
+		return;
+	if (data->host_cookie) {
+		data->host_cookie &= ~MSDC_ASYNC_FLAG;
+		msdc_unprepare_data(host, mrq);
+	}
+}
+
+static void msdc_data_xfer_next(struct msdc_host *host,
+				struct mmc_request *mrq, struct mmc_data *data)
+{
+	if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
+			(!data->bytes_xfered || !mrq->sbc))
+		msdc_start_command(host, mrq, mrq->stop);
+	else
+		msdc_request_done(host, mrq);
+}
+
+static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
+				struct mmc_request *mrq, struct mmc_data *data)
+{
+	struct mmc_command *stop = data->stop;
+	unsigned long flags;
+	bool done;
+
+	bool check_data = (events &
+	    (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO
+	     | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
+	     | MSDC_INT_DMA_PROTECT));
+
+	spin_lock_irqsave(&host->lock, flags);
+	done = !host->data;
+	if (check_data)
+		host->data = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (done)
+		return true;
+
+	if (check_data || (stop && stop->error)) {
+		dev_dbg(host->dev, "DMA status: 0x%8X\n",
+				readl(host->base + MSDC_DMA_CFG));
+		sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
+				1);
+		while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
+			;
+		mb(); /* wait for pending IO to finish */
+		sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
+		dev_dbg(host->dev, "DMA stop\n");
+
+		if ((events & MSDC_INT_XFER_COMPL) && (!stop || !stop->error)) {
+			data->bytes_xfered = data->blocks * data->blksz;
+		} else {
+			dev_err(host->dev, "interrupt events: %x\n", events);
+			msdc_reset_hw(host);
+			host->error |= REQ_DAT_ERR;
+			data->bytes_xfered = 0;
+
+			if (events & MSDC_INT_DATTMO)
+				data->error = -ETIMEDOUT;
+
+			dev_err(host->dev, "%s: cmd=%d; blocks=%d",
+				__func__, mrq->cmd->opcode, data->blocks);
+			dev_err(host->dev, "data_error=%d xfer_size=%d\n",
+					(int)data->error, data->bytes_xfered);
+		}
+
+		msdc_data_xfer_next(host, mrq, data);
+		done = true;
+	}
+	return done;
+}
+
+static void msdc_set_buswidth(struct msdc_host *host, u32 width)
+{
+	u32 val = readl(host->base + SDC_CFG);
+
+	val &= ~SDC_CFG_BUSWIDTH;
+
+	switch (width) {
+	default:
+	case MMC_BUS_WIDTH_1:
+		val |= (MSDC_BUS_1BITS << 16);
+		break;
+	case MMC_BUS_WIDTH_4:
+		val |= (MSDC_BUS_4BITS << 16);
+		break;
+	case MMC_BUS_WIDTH_8:
+		val |= (MSDC_BUS_8BITS << 16);
+		break;
+	}
+
+	writel(val, host->base + SDC_CFG);
+	dev_dbg(host->dev, "Bus Width = %d", width);
+}
+
+static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct msdc_host *host = mmc_priv(mmc);
+	int min_uv, max_uv;
+	int ret = 0;
+
+	if (!IS_ERR(mmc->supply.vqmmc)) {
+
+		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+			min_uv = 3300000;
+			max_uv = 3300000;
+		} else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+			min_uv = 1800000;
+			max_uv = 1800000;
+		} else {
+			dev_err(host->dev, "Unsupported signal voltage!\n");
+			return -EINVAL;
+		}
+
+		ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);
+		if (ret) {
+			dev_err(host->dev,
+					"Regulator set error %d: %d - %d\n",
+					ret, min_uv, max_uv);
+		}
+	}
+
+	return ret;
+}
+
+static void msdc_request_timeout(struct work_struct *work)
+{
+	struct msdc_host *host = container_of(work, struct msdc_host,
+			req_timeout.work);
+
+	/* simulate HW timeout status */
+	dev_err(host->dev, "%s: aborting cmd/data/mrq\n", __func__);
+	if (host->mrq) {
+		dev_err(host->dev, "%s: aborting mrq=%p cmd=%d\n", __func__,
+				host->mrq, host->mrq->cmd->opcode);
+		if (host->cmd) {
+			dev_err(host->dev, "%s: aborting cmd=%d\n",
+					__func__, host->cmd->opcode);
+			msdc_cmd_done(host, MSDC_INT_CMDTMO, host->mrq,
+					host->cmd);
+		} else if (host->data) {
+			dev_err(host->dev, "%s: abort data: cmd%d; %d blocks\n",
+					__func__, host->mrq->cmd->opcode,
+					host->data->blocks);
+			msdc_data_xfer_done(host, MSDC_INT_DATTMO, host->mrq,
+					host->data);
+		}
+	}
+}
+
+static irqreturn_t msdc_irq(int irq, void *dev_id)
+{
+	struct msdc_host *host = (struct msdc_host *) dev_id;
+
+	while (true) {
+		unsigned long flags;
+		struct mmc_request *mrq;
+		struct mmc_command *cmd;
+		struct mmc_data *data;
+		u32 events, event_mask;
+
+		spin_lock_irqsave(&host->lock, flags);
+		events = readl(host->base + MSDC_INT);
+		event_mask = readl(host->base + MSDC_INTEN);
+		/* clear interrupts */
+		writel(events & event_mask, host->base + MSDC_INT);
+
+		mrq = host->mrq;
+		cmd = host->cmd;
+		data = host->data;
+		spin_unlock_irqrestore(&host->lock, flags);
+
+		if (!(events & event_mask))
+			break;
+
+		if (!mrq) {
+			dev_err(host->dev,
+				"%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
+				__func__, events, event_mask);
+			WARN_ON(1);
+			break;
+		}
+
+		dev_dbg(host->dev, "%s: events=%08X\n", __func__, events);
+
+		if (cmd)
+			msdc_cmd_done(host, events, mrq, cmd);
+		else if (data)
+			msdc_data_xfer_done(host, events, mrq, data);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void msdc_init_hw(struct msdc_host *host)
+{
+	u32 val;
+	/* Configure to MMC/SD mode */
+	sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC);
+
+	/* Reset */
+	msdc_reset_hw(host);
+
+	/* Disable card detection */
+	sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
+
+	/* Disable and clear all interrupts */
+	writel(0, host->base + MSDC_INTEN);
+	val = readl(host->base + MSDC_INT);
+	writel(val, host->base + MSDC_INT);
+
+	writel(0, host->base + MSDC_PAD_TUNE);
+	writel(0, host->base + MSDC_IOCON);
+	sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+	writel(0x403c004f, host->base + MSDC_PATCH_BIT);
+	sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
+	writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
+	/* Configure to enable SDIO mode.
+	   it's must otherwise sdio cmd5 failed */
+	sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
+
+	/* disable detect SDIO device interrupt function */
+	sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
+
+	/* Configure to default data timeout */
+	sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
+	msdc_set_buswidth(host, MMC_BUS_WIDTH_1);
+
+	dev_dbg(host->dev, "init hardware done!");
+}
+
+static void msdc_deinit_hw(struct msdc_host *host)
+{
+	u32 val;
+	/* Disable and clear all interrupts */
+	writel(0, host->base + MSDC_INTEN);
+
+	val = readl(host->base + MSDC_INT);
+	writel(val, host->base + MSDC_INT);
+
+	msdc_gate_clock(host);
+
+	if (!IS_ERR(host->h_clk))
+		clk_disable_unprepare(host->h_clk);
+}
+
+/* init gpd and bd list in msdc_drv_probe */
+static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
+{
+	struct mt_gpdma_desc *gpd = dma->gpd;
+	struct mt_bdma_desc *bd = dma->bd;
+	int i;
+
+	memset(gpd, 0, sizeof(struct mt_gpdma_desc));
+	gpd->next = 0; /* only one gpd */
+
+	gpd->first_u32 |= GPDMA_DESC_BDP; /* hwo, cs, bd pointer */
+	gpd->ptr = (u32)dma->bd_addr; /* physical address */
+
+	memset(bd, 0, sizeof(struct mt_bdma_desc) * MAX_BD_NUM);
+
+	for (i = 0; i < (MAX_BD_NUM - 1); i++)
+		bd[i].next = (u32)dma->bd_addr + sizeof(*bd) * (i + 1);
+}
+
+static int timing_is_uhs(struct mmc_ios *ios)
+{
+	if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_330)
+		return 1;
+
+	return 0;
+}
+
+static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct msdc_host *host = mmc_priv(mmc);
+	int ret;
+	u32 ddr = 0;
+
+	if (ios->timing == MMC_TIMING_UHS_DDR50 ||
+		ios->timing == MMC_TIMING_MMC_DDR52)
+		ddr = 1;
+
+	msdc_set_buswidth(host, ios->bus_width);
+
+	/* Suspend/Resume will do power off/on */
+	switch (ios->power_mode) {
+	case MMC_POWER_UP:
+		msdc_init_hw(host);
+		if (!IS_ERR(mmc->supply.vmmc)) {
+			ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+					ios->vdd);
+			if (ret) {
+				dev_err(host->dev, "Failed to set vmmc power!\n");
+				return;
+			}
+		}
+		break;
+	case MMC_POWER_ON:
+		if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
+			ret = regulator_enable(mmc->supply.vqmmc);
+			if (ret)
+				dev_err(host->dev, "Failed to set vqmmc power!\n");
+			else
+				host->vqmmc_enabled = true;
+		}
+		msdc_ungate_clock(host);
+		break;
+	case MMC_POWER_OFF:
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
+		if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
+			regulator_disable(mmc->supply.vqmmc);
+			host->vqmmc_enabled = false;
+		}
+		msdc_gate_clock(host);
+		break;
+	default:
+		break;
+	}
+
+	/* Apply different pinctrl settings for different timing */
+	if (timing_is_uhs(ios))
+		pinctrl_select_state(host->pinctrl, host->pins_uhs);
+	else
+		pinctrl_select_state(host->pinctrl, host->pins_default);
+
+	if (host->mclk != ios->clock || host->ddr != ddr)
+		msdc_set_mclk(host, ddr, ios->clock);
+}
+
+static struct mmc_host_ops mt_msdc_ops = {
+	.post_req = msdc_post_req,
+	.pre_req = msdc_pre_req,
+	.request = msdc_ops_request,
+	.set_ios = msdc_ops_set_ios,
+	.start_signal_voltage_switch = msdc_ops_switch_volt,
+};
+
+static int msdc_drv_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct msdc_host *host;
+	struct resource *res;
+	int ret;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No DT found\n");
+		return -EINVAL;
+	}
+	/* Allocate MMC host for this device */
+	mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	host = mmc_priv(mmc);
+	ret = mmc_of_parse(mmc);
+	if (ret)
+		goto host_free;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->base)) {
+		ret = PTR_ERR(host->base);
+		goto host_free;
+	}
+
+	ret = mmc_regulator_get_supply(mmc);
+	if (ret == -EPROBE_DEFER)
+		goto host_free;
+
+	host->src_clk = devm_clk_get(&pdev->dev, "source");
+	if (IS_ERR(host->src_clk)) {
+		ret = PTR_ERR(host->src_clk);
+		goto host_free;
+	}
+
+	host->h_clk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(host->h_clk)) {
+		/* host->h_clk is optional, Only for MSDC0/3 at MT8173 */
+		dev_dbg(&pdev->dev,
+				"Invalied hclk from the device tree!\n");
+	} else {
+		clk_prepare_enable(host->h_clk);
+		dev_dbg(&pdev->dev,
+				"hclk rate: %ld\n", clk_get_rate(host->h_clk));
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq < 0) {
+		ret = -EINVAL;
+		goto host_free;
+	}
+
+	host->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(host->pinctrl)) {
+		ret = PTR_ERR(host->pinctrl);
+		dev_err(&pdev->dev, "Cannot find pinctrl!\n");
+		goto host_free;
+	}
+
+	host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
+	if (IS_ERR(host->pins_default)) {
+		ret = PTR_ERR(host->pins_default);
+		dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
+		goto host_free;
+	}
+
+	host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
+	if (IS_ERR(host->pins_uhs)) {
+		ret = PTR_ERR(host->pins_uhs);
+		dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
+		goto host_free;
+	}
+
+	host->dev = &pdev->dev;
+	host->mmc = mmc;
+	host->hclk = clk_get_rate(host->src_clk);
+	/* Set host parameters to mmc */
+	mmc->ops = &mt_msdc_ops;
+	mmc->f_min = host->hclk / (4 * 255);
+
+	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+	/* MMC core transfer sizes tunable parameters */
+	mmc->max_segs = MAX_BD_NUM;
+	mmc->max_seg_size = (64 * 1024 - 512);
+	mmc->max_blk_size = 2048;
+	mmc->max_req_size = 512 * 1024;
+	mmc->max_blk_count = mmc->max_req_size;
+
+	host->timeout_clks = 3 * 1048576;
+	host->dma.gpd = dma_alloc_coherent(&pdev->dev,
+				sizeof(struct mt_gpdma_desc),
+				&host->dma.gpd_addr, GFP_KERNEL);
+	host->dma.bd = dma_alloc_coherent(&pdev->dev,
+				MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+				&host->dma.bd_addr, GFP_KERNEL);
+	if ((!host->dma.gpd) || (!host->dma.bd)) {
+		ret = -ENOMEM;
+		goto release_mem;
+	}
+	msdc_init_gpd_bd(host, &host->dma);
+	INIT_DELAYED_WORK(&host->req_timeout, msdc_request_timeout);
+	spin_lock_init(&host->lock);
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = devm_request_irq(&pdev->dev, (unsigned int) host->irq, msdc_irq,
+		IRQF_TRIGGER_LOW | IRQF_ONESHOT, pdev->name, host);
+	if (ret)
+		goto release;
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto release;
+
+	return 0;
+
+release:
+	platform_set_drvdata(pdev, NULL);
+	msdc_deinit_hw(host);
+release_mem:
+	if (host->dma.gpd)
+		dma_free_coherent(&pdev->dev,
+			sizeof(struct mt_gpdma_desc),
+			host->dma.gpd, host->dma.gpd_addr);
+	if (host->dma.bd)
+		dma_free_coherent(&pdev->dev,
+			MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+			host->dma.bd, host->dma.bd_addr);
+host_free:
+	mmc_free_host(mmc);
+
+	return ret;
+}
+
+static int msdc_drv_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct msdc_host *host;
+
+	mmc = platform_get_drvdata(pdev);
+	host = mmc_priv(mmc);
+
+	platform_set_drvdata(pdev, NULL);
+	mmc_remove_host(host->mmc);
+	msdc_deinit_hw(host);
+
+	dma_free_coherent(&pdev->dev,
+			sizeof(struct mt_gpdma_desc),
+			host->dma.gpd, host->dma.gpd_addr);
+	dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+			host->dma.bd, host->dma.bd_addr);
+
+	mmc_free_host(host->mmc);
+
+	return 0;
+}
+
+static const struct of_device_id msdc_of_ids[] = {
+	{   .compatible = "mediatek,mt8135-mmc", },
+	{}
+};
+
+static struct platform_driver mt_msdc_driver = {
+	.probe = msdc_drv_probe,
+	.remove = msdc_drv_remove,
+	.driver = {
+		.name = "mtk-msdc",
+		.of_match_table = msdc_of_ids,
+	},
+};
+
+module_platform_driver(mt_msdc_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek SD/MMC Card Driver");
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:42 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:42 +0800
Subject: [PATCH v3 4/7] arm64: dts: mediatek: Add MT8173 MMC dts
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-5-git-send-email-chaotian.jing@mediatek.com>

From: Eddie Huang <eddie.huang at mediatek.com>

Add node mmc0 and mmc1

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 115 ++++++++++++++++++++++++++++
 arch/arm64/boot/dts/mediatek/mt8173.dtsi    |  22 +++++-
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index b1560c9..5312f07 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -33,6 +33,121 @@
 	chosen { };
 };
 
+&mmc0 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	status = "okay";
+	bus-width = <8>;
+	max-frequency = <50000000>;
+	cap-mmc-highspeed;
+	vmmc-supply = <&mt6397_vemc_3v3_reg>;
+	non-removable;
+};
+
+&mmc1 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_uhs>;
+	status = "okay";
+	bus-width = <4>;
+	max-frequency = <50000000>;
+	cap-sd-highspeed;
+	sd-uhs-sdr25;
+	cd-gpios = <&pio 132 0>;
+	vmmc-supply = <&mt6397_vmch_reg>;
+	vqmmc-supply = <&mt6397_vmc_reg>;
+};
+
+&pio {
+	mmc0_pins_default: mmc0default {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_57_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+				<MT8173_PIN_58_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+				<MT8173_PIN_59_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+				<MT8173_PIN_60_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+				<MT8173_PIN_61_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+				<MT8173_PIN_62_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+				<MT8173_PIN_63_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+				<MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+				<MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD>,
+				<MT8173_PIN_68_MSDC0_RST___FUNC_MSDC0_RSTB>;
+				bias-pull-up;
+		};
+		pins_clk {
+			pinmux =  <MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK>;
+				bias-pull-down;
+		};
+	};
+
+	mmc1_pins_default: mmc1default {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_73_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+			     <MT8173_PIN_74_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+			     <MT8173_PIN_75_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+			     <MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+			     <MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			bias-pull-down;
+			drive-strength = <MTK_DRIVE_4mA>;
+		};
+
+		pins_insert {
+			pinmux = <MT8173_PIN_132_I2S0_DATA1__FUNC_GPIO132>;
+			bias-pull-up;
+		};
+	};
+
+	mmc0_pins_uhs: mmc0 at 0{
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_57_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+				<MT8173_PIN_58_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+				<MT8173_PIN_59_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+				<MT8173_PIN_60_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+				<MT8173_PIN_61_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+				<MT8173_PIN_62_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+				<MT8173_PIN_63_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+				<MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+				<MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD>,
+				<MT8173_PIN_68_MSDC0_RST___FUNC_MSDC0_RSTB>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_2mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK>;
+			drive-strength = <MTK_DRIVE_2mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+
+	mmc1_pins_uhs: mmc1 at 0 {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_73_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+			     <MT8173_PIN_74_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+			     <MT8173_PIN_75_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+			     <MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+			     <MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+	};
+};
+
 &pwrap {
 	pmic: mt6397 {
 		compatible = "mediatek,mt6397";
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index d2aed57..8346c0f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -251,7 +251,27 @@
 			clock-names = "baud", "bus";
 			status = "disabled";
 		};
-	};
 
+		mmc0: mmc at 11230000 {
+			compatible = "mediatek,mt8173-mmc",
+				     "mediatek,mt8135-mmc";
+			reg = <0 0x11230000 0 0x108>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_MSDC30_0>,
+				 <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
+			clock-names = "source", "hclk";
+			status = "disabled";
+		};
+
+		mmc1: mmc at 11240000 {
+			compatible = "mediatek,mt8173-mmc",
+				     "mediatek,mt8135-mmc";
+			reg = <0 0x11240000 0 0x108>;
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_MSDC30_1>;
+			clock-names = "source";
+			status = "disabled";
+		};
+	};
 };
 
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:43 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:43 +0800
Subject: [PATCH v3 5/7] arm64: mediatek: Add Mediatek MMC support in defconfig
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-6-git-send-email-chaotian.jing@mediatek.com>

From: Eddie Huang <eddie.huang at mediatek.com>

Add CONFIG_MMC_MTK=y in defconfig

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5c09974..5a47fce 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -140,6 +140,7 @@ CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SPI=y
+CONFIG_MMC_MTK=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_EFI=y
 CONFIG_RTC_DRV_XGENE=y
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:44 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:44 +0800
Subject: [PATCH v3 6/7] ARM: mediatek: dts: Add emmc support to mt8135
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-7-git-send-email-chaotian.jing@mediatek.com>

From: Yingjoe Chen <yingjoe.chen at mediatek.com>

Add emmc node for mt8135.dtsi & mt8135-evbp1.dts

Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 arch/arm/boot/dts/mt8135-evbp1.dts | 141 +++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/mt8135.dtsi      |  26 +++++++
 2 files changed, 167 insertions(+)

diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
index 357a91f..6d2fee9 100644
--- a/arch/arm/boot/dts/mt8135-evbp1.dts
+++ b/arch/arm/boot/dts/mt8135-evbp1.dts
@@ -24,6 +24,147 @@
 	};
 };
 
+&mmc0 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	status = "okay";
+	bus-width = <8>;
+	max-frequency = <50000000>;
+	cap-mmc-highspeed;
+	vmmc-supply = <&mt6397_vemc_3v3_reg>;
+	non-removable;
+	func = "EMMC";
+};
+
+&mmc1 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_uhs>;
+	status = "okay";
+	bus-width = <4>;
+	max-frequency = <50000000>;
+	vmmc-supply = <&mt6397_vmch_reg>;
+	vqmmc-supply = <&mt6397_vmc_reg>;
+	cd-gpios = <&pio 63 0>;
+	cap-sd-highspeed;
+	sd-uhs-sdr25;
+	func = "SDCARD";
+};
+
+&pio {
+	mmc0_pins_default: mmc0default {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_0_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+				<MT8135_PIN_1_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+				<MT8135_PIN_2_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+				<MT8135_PIN_3_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+				<MT8135_PIN_4_MSDC0_CMD__FUNC_MSDC0_CMD>,
+				<MT8135_PIN_6_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+				<MT8135_PIN_7_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+				<MT8135_PIN_8_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+				<MT8135_PIN_9_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+				<MT8135_PIN_33_MSDC0_RSTB__FUNC_MSDC0_RSTB>;
+			bias-pull-up;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_5_MSDC0_CLK__FUNC_MSDC0_CLK>;
+			bias-pull-down;
+		};
+	};
+
+	mmc1_pins_default: mmc1default {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_83_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+			     <MT8135_PIN_84_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+			     <MT8135_PIN_85_MSDC1_CMD__FUNC_MSDC1_CMD>,
+			     <MT8135_PIN_87_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+			     <MT8135_PIN_88_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+			     <MT8135_PIN_63_MSDC1_INSI__FUNC_MSDC1_INSI>;
+			bias-pull-up;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_86_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			bias-pull-down;
+		};
+	};
+
+	mmc2_pins_default: mmc2default {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+			     <MT8135_PIN_81_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+			     <MT8135_PIN_79_MSDC2_CMD__FUNC_MSDC2_CMD>,
+			     <MT8135_PIN_77_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+			     <MT8135_PIN_78_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
+			     <MT8135_PIN_65_MSDC2_INSI__FUNC_MSDC2_INSI>;
+			bias-pull-up;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_80_MSDC2_CLK__FUNC_MSDC2_CLK>;
+		bias-pull-down;
+		};
+	};
+
+	mmc0_pins_uhs: mmc0 at 0 {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_0_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+			     <MT8135_PIN_1_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+			     <MT8135_PIN_2_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+			     <MT8135_PIN_3_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+			     <MT8135_PIN_4_MSDC0_CMD__FUNC_MSDC0_CMD>,
+			     <MT8135_PIN_6_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+			     <MT8135_PIN_7_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+			     <MT8135_PIN_8_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+			     <MT8135_PIN_9_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+			     <MT8135_PIN_33_MSDC0_RSTB__FUNC_MSDC0_RSTB>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_5_MSDC0_CLK__FUNC_MSDC0_CLK>;
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+
+	mmc1_pins_uhs: mmc1 at 0 {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_83_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+			     <MT8135_PIN_84_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+			     <MT8135_PIN_85_MSDC1_CMD__FUNC_MSDC1_CMD>,
+			     <MT8135_PIN_87_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+			     <MT8135_PIN_88_MSDC1_DAT3__FUNC_MSDC1_DAT3>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_86_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+	};
+
+	mmc2_pins_uhs: mmc2 at 0 {
+		pins_cmd_dat {
+			pinmux = <MT8135_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+			     <MT8135_PIN_81_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+			     <MT8135_PIN_79_MSDC2_CMD__FUNC_MSDC2_CMD>,
+			     <MT8135_PIN_77_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+			     <MT8135_PIN_78_MSDC2_DAT3__FUNC_MSDC2_DAT3>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+		pins_clk {
+			pinmux = <MT8135_PIN_80_MSDC2_CLK__FUNC_MSDC2_CLK>;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+	};
+};
+
 &pwrap {
 	pmic: mt6397 {
 		compatible = "mediatek,mt6397";
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 4d1ddd9..2c5c4da 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -212,5 +212,31 @@
 			status = "disabled";
 		};
 
+		mmc0: mmc at 11230000 {
+			compatible = "mediatek,mt8135-mmc";
+			reg = <0 0x11230000 0 0x108>;
+			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_MSDC20_1>;
+			clock-names = "source";
+			status = "disabled";
+		};
+
+		mmc1: mmc at 11240000 {
+			compatible = "mediatek,mt8135-mmc";
+			reg = <0 0x11240000 0 0x108>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_MSDC20_2>;
+			clock-names = "source";
+			status = "disabled";
+		};
+
+		mmc2: mmc at 11250000 {
+			compatible = "mediatek,mt8135-mmc";
+			reg = <0 0x11250000 0 0x108>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_MSDC30_1>;
+			clock-names = "source";
+			status = "disabled";
+		};
 	};
 };
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Tue Apr 28 02:48:45 2015
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Tue, 28 Apr 2015 17:48:45 +0800
Subject: [PATCH 7/7] ARM: multi_v7_defconfig: Enable Mediatek MMC support
 multi-v7
In-Reply-To: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1430214525-19198-8-git-send-email-chaotian.jing@mediatek.com>

From: Yingjoe Chen <yingjoe.chen at mediatek.com>

Add CONFIG_MMC_MTK=y in defconfig

Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index bc673e7..35447b2 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -451,6 +451,7 @@ CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SH_MMCIF=y
 CONFIG_MMC_SUNXI=y
+CONFIG_MMC_MTK=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
-- 
1.8.1.1.dirty



From lee.jones at linaro.org  Tue Apr 28 03:02:06 2015
From: lee.jones at linaro.org (Lee Jones)
Date: Tue, 28 Apr 2015 11:02:06 +0100
Subject: [PATCH v6 0/3] ARM: mediatek: Add driver for Mediatek I2C
In-Reply-To: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <20150428100206.GL11956@x1>

On Tue, 28 Apr 2015, Eddie Huang wrote:

> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller
> 
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
>  drivers/i2c/busses/Kconfig                         |   9 +
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
>  4 files changed, 799 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
>  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

Why have you sent me this?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From lee.jones at linaro.org  Tue Apr 28 03:07:19 2015
From: lee.jones at linaro.org (Lee Jones)
Date: Tue, 28 Apr 2015 11:07:19 +0100
Subject: [PATCH v3 1/3] mfd: provide RTC resource in MT6397 MFD
In-Reply-To: <1430206556-18254-2-git-send-email-eddie.huang@mediatek.com>
References: <1430206556-18254-1-git-send-email-eddie.huang@mediatek.com>
 <1430206556-18254-2-git-send-email-eddie.huang@mediatek.com>
Message-ID: <20150428100719.GN11956@x1>

On Tue, 28 Apr 2015, Eddie Huang wrote:

> Provide MT6397 RTC interrupt, base address, and register in
> MT6397 MFD.
> 
> Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
> ---
>  drivers/mfd/mt6397-core.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)

*after* Uwe's concerns have been attended to, you may add my:

Acked-by: Lee Jones <lee.jones at linaro.org>

FWIW, I quite like straight lines. :)

> diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> index 09bc780..08cfbd1 100644
> --- a/drivers/mfd/mt6397-core.c
> +++ b/drivers/mfd/mt6397-core.c
> @@ -21,9 +21,27 @@
>  #include <linux/mfd/mt6397/core.h>
>  #include <linux/mfd/mt6397/registers.h>
>  
> +#define MT6397_RTC_BASE		0xe000
> +#define MT6397_RTC_SIZE		0x3e
> +
> +static const struct resource mt6397_rtc_resources[] = {
> +	{
> +		.start = MT6397_RTC_BASE,
> +		.end   = MT6397_RTC_BASE + MT6397_RTC_SIZE,
> +		.flags  = IORESOURCE_MEM,
> +	},
> +	{
> +		.start = MT6397_IRQ_RTC,
> +		.end   = MT6397_IRQ_RTC,
> +		.flags  = IORESOURCE_IRQ,
> +	},
> +};
> +
>  static const struct mfd_cell mt6397_devs[] = {
>  	{
>  		.name = "mt6397-rtc",
> +		.num_resources = ARRAY_SIZE(mt6397_rtc_resources),
> +		.resources = mt6397_rtc_resources,
>  		.of_compatible = "mediatek,mt6397-rtc",
>  	}, {
>  		.name = "mt6397-regulator",

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From jdelvare at suse.de  Tue Apr 28 03:08:12 2015
From: jdelvare at suse.de (Jean Delvare)
Date: Tue, 28 Apr 2015 12:08:12 +0200
Subject: [PATCH v6 0/3] ARM: mediatek: Add driver for Mediatek I2C
In-Reply-To: <20150428100206.GL11956@x1>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
 <20150428100206.GL11956@x1>
Message-ID: <1430215692.4445.16.camel@chaos.site>

Hi Lee, Eddie,

Le Tuesday 28 April 2015 ? 11:02 +0100, Lee Jones a ?crit :
> On Tue, 28 Apr 2015, Eddie Huang wrote:
> 
> > This series is for Mediatek SoCs I2C controller common bus driver.
> > 
> > Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> > New generation SoC like MT8173 fix following limitations:
> > 
> > 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> > mode. WRRD can have two i2c_msg numbers.
> > 
> > 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> > mode the Repeat Start will be issued between 2 messages.
> > In this driver if 2 messages is first write then read, the driver will
> > combine 2 messages using Write-Read mode so the RS will be issued between
> > the 2 messages.
> > 
> > 3. The max transfer data length is 255 in one message. In WRRD mode, the
> > max data length of second msg is 31.
> > 
> > MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> > registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> > bit first, the operation on other registers are still the same.
> > For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> > For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> > the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> > "mediatek,have-pmic" property in the .dts file of each platform.
> > 
> > This driver is based on 4.1-rc1.
> > 
> > Change in v6:
> > 1. Update binding document not use default clock-frequency as example.
> > 2. Add mtk_i2c_compatible struct and pass hardware capabilities
> >    through of_device_id
> > 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
> >    so just init one time.
> > 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> > 
> > Change in v5:
> > Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> > dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> > return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> > Add MT8173 I2C driver.
> > 
> > Change in v4:
> > Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> > Remove check transfer size and WRRD combine code. Instead, fill quirk
> > property and let i2c_check_for_quirks to do the filter.
> > 
> > [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> > [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> > 
> > Eddie Huang (1):
> >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > 
> > Xudong Chen (2):
> >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> >   I2C: mediatek: Add driver for MediaTek I2C controller
> > 
> >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> >  drivers/i2c/busses/Kconfig                         |   9 +
> >  drivers/i2c/busses/Makefile                        |   1 +
> >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> >  4 files changed, 799 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> 
> Why have you sent me this?

Mind you, I was wondering exactly the same ;-)


-- 
Jean Delvare
SUSE L3 Support



From s.hauer at pengutronix.de  Tue Apr 28 05:37:25 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 28 Apr 2015 14:37:25 +0200
Subject: [PATCH v3 6/7] ARM: mediatek: dts: Add emmc support to mt8135
In-Reply-To: <1430214525-19198-7-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
 <1430214525-19198-7-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150428123725.GK6325@pengutronix.de>

On Tue, Apr 28, 2015 at 05:48:44PM +0800, Chaotian Jing wrote:
> From: Yingjoe Chen <yingjoe.chen at mediatek.com>
> 
> Add emmc node for mt8135.dtsi & mt8135-evbp1.dts
> 
> Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  arch/arm/boot/dts/mt8135-evbp1.dts | 141 +++++++++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/mt8135.dtsi      |  26 +++++++
>  2 files changed, 167 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
> index 357a91f..6d2fee9 100644
> --- a/arch/arm/boot/dts/mt8135-evbp1.dts
> +++ b/arch/arm/boot/dts/mt8135-evbp1.dts
> @@ -24,6 +24,147 @@
>  	};
>  };
>  
> +&mmc0 {
> +	pinctrl-names = "default", "state_uhs";
> +	pinctrl-0 = <&mmc0_pins_default>;
> +	pinctrl-1 = <&mmc0_pins_uhs>;
> +	status = "okay";
> +	bus-width = <8>;
> +	max-frequency = <50000000>;
> +	cap-mmc-highspeed;
> +	vmmc-supply = <&mt6397_vemc_3v3_reg>;
> +	non-removable;
> +	func = "EMMC";

...

> +	func = "SDCARD";

These have been removed in earlier versions, right?

> diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
> index 4d1ddd9..2c5c4da 100644
> --- a/arch/arm/boot/dts/mt8135.dtsi
> +++ b/arch/arm/boot/dts/mt8135.dtsi
> @@ -212,5 +212,31 @@
>  			status = "disabled";
>  		};
>  
> +		mmc0: mmc at 11230000 {
> +			compatible = "mediatek,mt8135-mmc";
> +			reg = <0 0x11230000 0 0x108>;

Please use the whole register space for the controller here, not only
the one actually used by the registers.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From eddie.huang at mediatek.com  Tue Apr 28 06:40:33 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 21:40:33 +0800
Subject: [PATCH v3 2/3] tty: serial: 8250_mtk: Add earlycon
In-Reply-To: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430228434-31779-3-git-send-email-eddie.huang@mediatek.com>

Add 8250 MTK UART driver to support earlycon device tree.
Earlycon take effect by
  add "earlycon" in kernel boot argument
  add "linux,sdtout-path" property in device tree file

Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/tty/serial/8250/8250_mtk.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 7a11fac..8b2a666 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -289,6 +289,19 @@ static struct platform_driver mtk8250_platform_driver = {
 };
 module_platform_driver(mtk8250_platform_driver);
 
+static int __init early_mtk8250_setup(struct earlycon_device *device,
+					const char *options)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->port.iotype = UPIO_MEM32;
+
+	return early_serial8250_setup(device, NULL);
+}
+
+OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup);
+
 MODULE_AUTHOR("Matthias Brugger");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Mediatek 8250 serial port driver");
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 06:40:31 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 21:40:31 +0800
Subject: [PATCH v3 0/3] tty: serial: Add earlycon support to MT8173 SoC 
Message-ID: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>

This patch add earlycon support to MT8173 SoC platform.
To use earlycon, need
1. Add earlycon in boot parameters
2. Add "linux,sdtout-path" property in device tree file

This patch based on 4.1-rc1.

Change in v3:
Remove noinit options, not necessary, because 8250_early.c will not init hardware
if not provide baudrate.

Change v2:
1. Add noinit options.
2. Remove duplicate code in 8250_mtk.c, reuse the 8250_early.c existed function.

Eddie Huang (3):
  tty: serial: 8250: export early_serial8250_setup function
  tty: serial: 8250_mtk: Add earlycon
  arm64: dts: Add mediatek MT8173 earlycon support

 arch/arm64/boot/dts/mediatek/mt8173-evb.dts |  4 +++-
 drivers/tty/serial/8250/8250_early.c        |  2 +-
 drivers/tty/serial/8250/8250_mtk.c          | 13 +++++++++++++
 include/linux/serial_8250.h                 |  2 ++
 4 files changed, 19 insertions(+), 2 deletions(-)

-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 06:40:34 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 21:40:34 +0800
Subject: [PATCH v3 3/3] arm64: dts: Add mediatek MT8173 earlycon support
In-Reply-To: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430228434-31779-4-git-send-email-eddie.huang@mediatek.com>

Add earlycon support to mediatek MT8173 evaluation board dts.

Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 43d5401..d4cf751 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -30,7 +30,9 @@
 		reg = <0 0x40000000 0 0x80000000>;
 	};
 
-	chosen { };
+	chosen {
+		linux,stdout-path = &uart0;
+	};
 };
 
 &uart0 {
-- 
1.8.1.1.dirty



From eddie.huang at mediatek.com  Tue Apr 28 06:40:32 2015
From: eddie.huang at mediatek.com (Eddie Huang)
Date: Tue, 28 Apr 2015 21:40:32 +0800
Subject: [PATCH v3 1/3] tty: serial: 8250: export early_serial8250_setup
 function
In-Reply-To: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <1430228434-31779-2-git-send-email-eddie.huang@mediatek.com>

8250-like uart driver may call early_serial8250_setup to
reuse 8250_early.c character output function.

Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
---
 drivers/tty/serial/8250/8250_early.c | 2 +-
 include/linux/serial_8250.h          | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 6c0fd8b..771dda2 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -131,7 +131,7 @@ static void __init init_port(struct earlycon_device *device)
 	serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
-static int __init early_serial8250_setup(struct earlycon_device *device,
+int __init early_serial8250_setup(struct earlycon_device *device,
 					 const char *options)
 {
 	if (!(device->port.membase || device->port.iobase))
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 78097e7..f0c68d8 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -137,6 +137,8 @@ extern int early_serial_setup(struct uart_port *port);
 
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
+extern int early_serial8250_setup(struct earlycon_device *device,
+					 const char *options);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
 extern int serial8250_do_startup(struct uart_port *port);
-- 
1.8.1.1.dirty



From yingjoe.chen at mediatek.com  Tue Apr 28 07:10:20 2015
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Tue, 28 Apr 2015 22:10:20 +0800
Subject: [PATCH 2/4] ARM: dts: mt8135: Add pmic wrapper nodes
In-Reply-To: <1429780875-29096-3-git-send-email-s.hauer@pengutronix.de>
References: <1429780875-29096-1-git-send-email-s.hauer@pengutronix.de>
 <1429780875-29096-3-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1430230220.32537.3.camel@mtksdaap41>

On Thu, 2015-04-23 at 11:21 +0200, Sascha Hauer wrote:
> This adds the pmic wrapper node to the MediaTek MT8135 dtsi file.
> 
> This unit is used to access the PMIC on MediaTek boards.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  arch/arm/boot/dts/mt8135.dtsi | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
> index b4017e2..b0f20fc 100644
> --- a/arch/arm/boot/dts/mt8135.dtsi
> +++ b/arch/arm/boot/dts/mt8135.dtsi
> @@ -15,6 +15,7 @@
>  #include <dt-bindings/clock/mt8135-clk.h>
>  #include <dt-bindings/interrupt-controller/irq.h>
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/reset-controller/mt8135-resets.h>
>  #include "skeleton64.dtsi"
>  
>  / {
> @@ -127,6 +128,19 @@
>  			reg = <0 0x10003000 0 0x1000>;
>  		};
>  
> +		pwrap: pwrap at 1000f000 {
> +			compatible = "mediatek,mt8135-pwrap";
> +			reg = <0 0x1000f000 0 0x1000>,
> +				<0 0x11017000 0 0x1000>;
> +			reg-names = "pwrap", "pwrap-bridge";
> +			interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
> +			resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
> +					<&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
> +			reset-names = "pwrap", "pwrap-bridge";
> +			clocks = <&clk26m>, <&clk26m>;
> +			clock-names = "spi", "wrap";
> +		};
> +
>  		timer: timer at 10008000 {

Hi Sascha,

It seems we have many 8135 dtsi updates recently.
Please sort according to node instance address so it will be easier to
merge or resolve conflict.

Joe.C





From rajeevkumar.linux at gmail.com  Tue Apr 28 22:18:25 2015
From: rajeevkumar.linux at gmail.com (rajeev kumar)
Date: Wed, 29 Apr 2015 10:48:25 +0530
Subject: [PATCH v6 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
In-Reply-To: <1430209869-6631-2-git-send-email-eddie.huang@mediatek.com>
References: <1430209869-6631-1-git-send-email-eddie.huang@mediatek.com>
 <1430209869-6631-2-git-send-email-eddie.huang@mediatek.com>
Message-ID: <CAA7nrtgcAU8RpUO=GPAWQH5hrsMg5jDzOJ-NqN_c19t_GPmTjw@mail.gmail.com>

On Tue, Apr 28, 2015 at 2:01 PM, Eddie Huang <eddie.huang at mediatek.com> wrote:
> From: Xudong Chen <xudong.chen at mediatek.com>
>
> Add devicetree bindings for Mediatek Soc I2C driver.
>
> Signed-off-by: Xudong Chen <xudong.chen at mediatek.com>
> Signed-off-by: Eddie Huang <eddie.huang at mediatek.com>
> ---
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> new file mode 100644
> index 0000000..0ce6fa3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> @@ -0,0 +1,41 @@
> +* Mediatek's I2C controller
> +
> +The Mediatek's I2C controller is used to interface with I2C devices.
> +
> +Required properties:
> +  - compatible: value should be either of the following.
> +      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
> +      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
> +      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
> +      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
> +      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
> +  - reg: physical base address of the controller and dma base, length of memory
> +    mapped region.
> +  - interrupts: interrupt number to the cpu.
> +  - clock-div: the fixed value for frequency divider of clock source in i2c
> +    module. Each IC may be different.
> +  - clocks: clock name from clock manager
> +  - clock-names: Must include "main" and "dma", if enable have-pmic need include
> +    "pmic" extra.
> +
> +Optional properties:
> +  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
> +    is 100000.

100000 HZ ...

> +  - mediatek,have-pmic: platform can control i2c form special pmic side.
> +    Only mt6589 and mt8135 support this feature.
> +  - mediatek,use-push-pull: IO config use push-pull mode.
> +
> +Example:
> +
> +       i2c0: i2c at 1100d000 {
> +                       compatible = "mediatek,mt6577-i2c";
> +                       reg = <0x1100d000 0x70>,
> +                             <0x11000300 0x80>;
> +                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
> +                       clock-frequency = <400000>;
> +                       mediatek,have-pmic;
> +                       clock-div = <16>;
> +                       clocks = <&i2c0_ck>, <&ap_dma_ck>;
> +                       clock-names = "main", "dma";
> +       };
> +
> --
> 1.8.1.1.dirty
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From viresh.kumar at linaro.org  Tue Apr 28 23:06:46 2015
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Wed, 29 Apr 2015 11:36:46 +0530
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <CALx668W_rj8_UBory5fVa4_i3vLCjgApYCwHoSthXNmx79yH1g@mail.gmail.com>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
 <20150423125620.GB29702@leverpostej>
 <CALx668W_rj8_UBory5fVa4_i3vLCjgApYCwHoSthXNmx79yH1g@mail.gmail.com>
Message-ID: <CAKohpokhbh3QoDsG=2q3YGLnhhoumOkipj_zdd-JPfVSA0X5cQ@mail.gmail.com>

On 24 April 2015 at 12:20, Pi-Cheng Chen <pi-cheng.chen at linaro.org> wrote:
> So even we have a new OPP binding to describe the OPP, we have to
> leave these table as they are for backward compatibility?

Yes.

I could find the below excerpts from [1]:

"The compatibility rules say that new kernels must work with older
device trees. If changes are required, they should be put into new
properties; the old ones can then be deprecated but not removed. New
properties should be optional, so that device trees lacking those
properties continue to work. The device tree developers will provide a
set of guidelines for the creation of future-proof bindings."

--
viresh

[1] http://lwn.net/Articles/572114/


From yong.wu at mediatek.com  Tue Apr 28 23:23:27 2015
From: yong.wu at mediatek.com (Yong Wu)
Date: Wed, 29 Apr 2015 14:23:27 +0800
Subject: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver
In-Reply-To: <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
References: <1425638900-24989-1-git-send-email-yong.wu@mediatek.com>
 <1425638900-24989-3-git-send-email-yong.wu@mediatek.com>
 <CAAFQd5ASywTX7P9L8cogBbBTra0W1=oVxeWfK5=K7L+SR2xaFA@mail.gmail.com>
 <1426677749.22581.38.camel@mhfsdcap03>
 <CAAFQd5DOzFmfXki8GwUC75VQFEWzxBUNUgOtSuRtV6tc27kD2A@mail.gmail.com>
Message-ID: <1430288607.24151.40.camel@mhfsdcap03>

Dear Tomasz,
     About a hardcode your comment, please help check below.

Dear Mark,
      I would like to add a item in the dtsi of mtk-iommu. Please also
help have a look.


> > > +static const struct mtk_iommu_port mtk_iommu_mt8173_port[] = {
> > > +       /* port name                m4uid slaveid larbid portid
tfid */
> > > +       /* larb0 */
> > > +       {"M4U_PORT_DISP_OVL0",          0,  0,    0,  0,
MTK_TFID(0, 0)},
> > > +       {"M4U_PORT_DISP_RDMA0",         0,  0,    0,  1,
MTK_TFID(0, 1)},
> > > +       {"M4U_PORT_DISP_WDMA0",         0,  0,    0,  2,
MTK_TFID(0, 2)},
> > > +       {"M4U_PORT_DISP_OD_R",          0,  0,    0,  3,
MTK_TFID(0, 3)},
> > > +       {"M4U_PORT_DISP_OD_W",          0,  0,    0,  4,
MTK_TFID(0, 4)},
> > > +       {"M4U_PORT_MDP_RDMA0",          0,  0,    0,  5,
MTK_TFID(0, 5)},
> > > +       {"M4U_PORT_MDP_WDMA",           0,  0,    0,  6,
MTK_TFID(0, 6)},
> > > +       {"M4U_PORT_MDP_WROT0",          0,  0,    0,  7,
MTK_TFID(0, 7)},
[...]
> 
> > > +};
> > > +
> > 
> > Anyway, is it really necessary to hardcode the SoC specific topology
> > data in this driver? Is there really any use besides of printing
port
> > name? If not, you could just print the values in a way letting you
> > quickly look up in the datasheet, without hardcoding this. Or even
> > better, you could print which devices are attached to the port.
> > 
> a) Printing the port name is for debug. We could not request every
iommu
> user to understand smi&local arbiter. When there is irq, they have to
> look up the iommu's datasheet to find out which port error. if we
print
> it directly, It may be more easily to debug.
> 
> b) In mtk_iommu_config_port, according to this hardcode we can be
easily
> to get out which local arbiter and which port we prepare to config.
> 
> c) If we support different SOCs, we could change this arrays easily.
> 
> > 
     There is no similar code in the others iommu, so I prepare to
delete it, But we really need know which local arbiter and which port we
are going to config(which port will enable iommu)
        so we prepare add a item in the dtsi like this:

	iommu: mmsys_iommu at 10205000 {
			compatible = "mediatek,mt8173-iommu";
			<...>
+			larb-portes-nr = <M4U_LARB0_PORT_NR
+					 M4U_LARB1_PORT_NR
+					 M4U_LARB2_PORT_NR
+					 M4U_LARB3_PORT_NR
+					 M4U_LARB4_PORT_NR
+					 M4U_LARB5_PORT_NR>;
			larb = <&larb0 &larb1 &larb2 &larb3 &larb4 &larb5>;
			#iommu-cells = <1>;
		};
	larb-portes-nr : the number of the portes in each local arbiter.
        
	If we have this item, we can get which larb and which port from the
portid in the dtsi of the iommu user.

        And while there is isr, I will print the larb-id and the port-id
instead of the string of the port name.

	The M4U_LARB0_PORT_NR/... will be added in
dt-bindings/iommu/mt8173-iommu-port.h[0]

Dear Mark, 
      As above, if I add this item in the dtsi of iommu, is it ok?


[0]:http://lists.linuxfoundation.org/pipermail/iommu/2015-March/012450.html
 



From s.hauer at pengutronix.de  Tue Apr 28 23:37:26 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 29 Apr 2015 08:37:26 +0200
Subject: [PATCH v3 4/7] arm64: dts: mediatek: Add MT8173 MMC dts
In-Reply-To: <1430214525-19198-5-git-send-email-chaotian.jing@mediatek.com>
References: <1430214525-19198-1-git-send-email-chaotian.jing@mediatek.com>
 <1430214525-19198-5-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <20150429063726.GQ6325@pengutronix.de>

On Tue, Apr 28, 2015 at 05:48:42PM +0800, Chaotian Jing wrote:
> From: Eddie Huang <eddie.huang at mediatek.com>
> 
> Add node mmc0 and mmc1

While at it you could add mmc2 and mmc3 to the dtsi aswell. No need to patch that
again later.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 28 23:44:54 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 29 Apr 2015 08:44:54 +0200
Subject: [PATCH v3 3/3] arm64: dts: Add mediatek MT8173 earlycon support
In-Reply-To: <1430228434-31779-4-git-send-email-eddie.huang@mediatek.com>
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
 <1430228434-31779-4-git-send-email-eddie.huang@mediatek.com>
Message-ID: <20150429064454.GR6325@pengutronix.de>

Hi Eddie,

On Tue, Apr 28, 2015 at 09:40:34PM +0800, Eddie Huang wrote:
> Add earlycon support to mediatek MT8173 evaluation board dts.

This is not about earlycon support. It adds the stdout-path property
which is generally about console. It only happens to used for earlycon,
but would be used as a regular console aswell if it wasn't broken for
some kernel revisisions.

>  
> -	chosen { };
> +	chosen {
> +		linux,stdout-path = &uart0;
> +	};

Please use stdout-path, without the 'linux,'.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 28 23:46:04 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 29 Apr 2015 08:46:04 +0200
Subject: [PATCH v3 0/3] tty: serial: Add earlycon support to MT8173 SoC
In-Reply-To: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
Message-ID: <20150429064604.GS6325@pengutronix.de>

On Tue, Apr 28, 2015 at 09:40:31PM +0800, Eddie Huang wrote:
> This patch add earlycon support to MT8173 SoC platform.
> To use earlycon, need
> 1. Add earlycon in boot parameters
> 2. Add "linux,sdtout-path" property in device tree file
> 
> This patch based on 4.1-rc1.
> 
> Change in v3:
> Remove noinit options, not necessary, because 8250_early.c will not init hardware
> if not provide baudrate.
> 
> Change v2:
> 1. Add noinit options.
> 2. Remove duplicate code in 8250_mtk.c, reuse the 8250_early.c existed function.
> 
> Eddie Huang (3):
>   tty: serial: 8250: export early_serial8250_setup function
>   tty: serial: 8250_mtk: Add earlycon
>   arm64: dts: Add mediatek MT8173 earlycon support

Works fine here:

Tested-by: Sascha Hauer <s.hauer at pengutronix.de>

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From Vineet.Gupta1 at synopsys.com  Wed Apr 29 01:19:02 2015
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 29 Apr 2015 08:19:02 +0000
Subject: [PATCH v3 3/3] arm64: dts: Add mediatek MT8173 earlycon support
References: <1430228434-31779-1-git-send-email-eddie.huang@mediatek.com>
 <1430228434-31779-4-git-send-email-eddie.huang@mediatek.com>
 <20150429064454.GR6325@pengutronix.de>
Message-ID: <C2D7FE5348E1B147BCA15975FBA230756659C0C2@IN01WEMBXB.internal.synopsys.com>

On Wednesday 29 April 2015 12:15 PM, Sascha Hauer wrote:
> Hi Eddie,
>
> On Tue, Apr 28, 2015 at 09:40:34PM +0800, Eddie Huang wrote:
>> Add earlycon support to mediatek MT8173 evaluation board dts.
> This is not about earlycon support. It adds the stdout-path property
> which is generally about console.

Indeed, this is shorter way of specifying the default console by referring to uart
device.

>  It only happens to used for earlycon,
> but would be used as a regular console aswell if it wasn't broken for
> some kernel revisisions.

Really - I'm confused. When I last tried this for arc_uart (in 3.17 time frame),
it would setup default console, but to use it for earlycon we needed
bootargs=earlycon in chosen. However I had to revet that change since OF core
still was fixing a few things in that area.

See mainline 22524b02b17b901f28 ("Revert "ARC: [arcfpga] stdout-path now suffices
for earlycon/console"")

-Vineet

>
>>  
>> -	chosen { };
>> +	chosen {
>> +		linux,stdout-path = &uart0;
>> +	};
> Please use stdout-path, without the 'linux,'.
>
> Sascha
>



From djkurtz at chromium.org  Wed Apr 29 23:38:31 2015
From: djkurtz at chromium.org (Daniel Kurtz)
Date: Thu, 30 Apr 2015 14:38:31 +0800
Subject: [PATCH 2/2] arm64: dts: mt8173: Fixup pinctrl nodes
In-Reply-To: <1430213037-23831-2-git-send-email-yingjoe.chen@mediatek.com>
References: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>
 <1430213037-23831-2-git-send-email-yingjoe.chen@mediatek.com>
Message-ID: <CAGS+omBmhsbVp0t2mPqrod-MkGi185tC0gcHvm0tHg4dHQr0cg@mail.gmail.com>

On Tue, Apr 28, 2015 at 5:23 PM, Yingjoe Chen <yingjoe.chen at mediatek.com> wrote:
>
> The 8173 pinctrl node doesn't follow dts convention. Fix them.
> Also add a comment to explain pinctrl register usage to make it
> more clear.
>
> Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>

Thanks for the fix.

Reviewed-by: Daniel Kurtz <djkurtz at chromium.org>

>
> ---
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> index 8346c0f..e4a30cd 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> @@ -128,6 +128,7 @@
>                 compatible = "simple-bus";
>                 ranges;
>
> +               /* Provide regmap for pinctrl driver */
>                 syscfg_pctl_a: syscfg_pctl_a at 10005000 {
>                         compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon";
>                         reg = <0 0x10005000 0 0x1000>;
> @@ -159,9 +160,13 @@
>                         #reset-cells = <1>;
>                 };
>
> -               pio: pinctrl at 0x10005000 {
> +               /*
> +                * Pinctrl access register at 0x10005000 through regmap.
> +                * Register 0x1000b000 is used by EINT.
> +                */
> +               pio: pinctrl at 10005000 {
>                         compatible = "mediatek,mt8173-pinctrl";
> -                       reg = <0 0x1000B000 0 0x1000>;
> +                       reg = <0 0x1000b000 0 0x1000>;
>                         mediatek,pctl-regmap = <&syscfg_pctl_a>;
>                         pins-are-numbered;
>                         gpio-controller;
> @@ -169,8 +174,8 @@
>                         interrupt-controller;
>                         #interrupt-cells = <2>;
>                         interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
> -                                               <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
> -                                               <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
> +                                    <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
> +                                    <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
>                 };
>
>                 sysirq: intpol-controller at 10200620 {
> --
> 1.8.1.1.dirty
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


From s.hauer at pengutronix.de  Thu Apr 30 00:42:18 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 30 Apr 2015 09:42:18 +0200
Subject: [PATCH 1/2] cpufreq: mediatek: Add MT8173 cpufreq driver
In-Reply-To: <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
References: <1429522047-16675-1-git-send-email-pi-cheng.chen@linaro.org>
 <1429522047-16675-2-git-send-email-pi-cheng.chen@linaro.org>
Message-ID: <20150430074218.GH4946@pengutronix.de>

On Mon, Apr 20, 2015 at 05:27:26PM +0800, pi-cheng.chen wrote:
> This patch implements MT8173 specific cpufreq driver with OPP table defined
> in the driver code.
> 
> Signed-off-by: pi-cheng.chen <pi-cheng.chen at linaro.org>
> ---
>  drivers/cpufreq/Kconfig.arm      |   6 +
>  drivers/cpufreq/Makefile         |   1 +
>  drivers/cpufreq/mt8173-cpufreq.c | 509 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 516 insertions(+)
>  create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 1b06fc4..25643c7 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> +
> +static int mt8173_cpufreq_dvfs_init(struct cpu_dvfs_info *info)
> +{
> +	struct device *cpu_dev;
> +	struct regulator *proc_reg, *sram_reg;
> +	struct clk *cpu_clk, *inter_pll;
> +	unsigned long rate;
> +	int cpu, ret;
> +
> +	cpu = cpumask_first(&info->cpus);
> +
> +try_next_cpu:
> +	cpu_dev = get_cpu_device(cpu);
> +	proc_reg = regulator_get_exclusive(cpu_dev, "proc");
> +	sram_reg = regulator_get_exclusive(cpu_dev, "sram");
> +	cpu_clk = clk_get(cpu_dev, "cpu");
> +	inter_pll = clk_get(cpu_dev, "intermediate");
> +
> +	if (IS_ERR_OR_NULL(proc_reg) || IS_ERR_OR_NULL(cpu_clk) ||
> +	    IS_ERR_OR_NULL(inter_pll)) {
> +		cpu = cpumask_next(cpu, &info->cpus);
> +		if (cpu >= nr_cpu_ids)
> +			return -ENODEV;
> +
> +		goto try_next_cpu;
> +	}

Please keep an eye on the error pathes. This one is quite broken. You
get references to resources here which you never release. Also
-EPROBE_DEFER is a valid return value from regulator_get which is not
handled here.

Also IS_ERR_OR_NULL() is most probably wrong here. Should be IS_ERR().

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Thu Apr 30 09:09:02 2015
From: matthias.bgg at gmail.com (Matthias Brugger_0)
Date: Thu, 30 Apr 2015 18:09:02 +0200
Subject: [PATCH 1/2] ARM: dts: mt8135: Add pinctrl/GPIO/EINT node for
 mt8135.
In-Reply-To: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>
References: <1430213037-23831-1-git-send-email-yingjoe.chen@mediatek.com>
Message-ID: <7612069.RRCsOqAebC@ubix>

On Tuesday, April 28, 2015 05:23:56 PM Yingjoe Chen wrote:
> From: Hongzhou Yang <hongzhou.yang at mediatek.com>
> 
> 
> Matthias,
> 
> Since mt8135 pinctrl node patch is not in v4.1-rc1, I'd like to make some
> minor change to follow dts convention.
> 
> Let me know what you think.
> Thanks.
> 
> Joe.C
> 
> ---8<--------------------------------------------------------------------
> Add pinctrl,GPIO and EINT node to mt8135.dtsi.
> 
> Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
> Signed-off-by: Hongzhou Yang <hongzhou.yang at mediatek.com>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  arch/arm/boot/dts/mt8135-pinfunc.h | 1302
> ++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/mt8135.dtsi      |  
> 31 +
>  2 files changed, 1333 insertions(+)
>  create mode 100644 arch/arm/boot/dts/mt8135-pinfunc.h
> 
> diff --git a/arch/arm/boot/dts/mt8135-pinfunc.h
> b/arch/arm/boot/dts/mt8135-pinfunc.h new file mode 100644
> index 0000000..5a60987
> --- /dev/null
> +++ b/arch/arm/boot/dts/mt8135-pinfunc.h
[...]
> diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
> index 2c5c4da..d6c1f14 100644
> --- a/arch/arm/boot/dts/mt8135.dtsi
> +++ b/arch/arm/boot/dts/mt8135.dtsi
> @@ -17,6 +17,7 @@
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>  #include <dt-bindings/reset-controller/mt8135-resets.h>
>  #include "skeleton64.dtsi"
> +#include "mt8135-pinfunc.h"
> 
>  / {
>  	compatible = "mediatek,mt8135";
> @@ -141,6 +142,36 @@
>  			clock-names = "spi", "wrap";
>  		};
> 
> +		/* Provide regmap for pinctrl driver */

I think from the DTS it is quite clear for what the node is used for.
Please delete the comment.

> +		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
> +			compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
> +			reg = <0 0x10005000 0 0x1000>;
> +		};
> +
> +		/* Provide regmap for pinctrl driver */

Same here.

> +		syscfg_pctl_b: syscfg_pctl_b at 1020c000 {
> +			compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
> +			reg = <0 0x1020c000 0 0x1000>;
> +		};

Please sort the nodes by it's address.

Cheers,
Matthias


From broonie at kernel.org  Thu Apr 30 13:12:07 2015
From: broonie at kernel.org (Mark Brown)
Date: Thu, 30 Apr 2015 21:12:07 +0100
Subject: [RESEND RFC PATCH 1/3] ASoC: mediatek: Add binding support for
 AFE driver
In-Reply-To: <1429672640.14162.55.camel@mtksdaap41>
References: <1428653649-38200-1-git-send-email-koro.chen@mediatek.com>
 <1428653649-38200-2-git-send-email-koro.chen@mediatek.com>
 <20150418173407.GE26185@sirena.org.uk>
 <20150420043747.GH6325@pengutronix.de>
 <20150420204849.GJ14892@sirena.org.uk>
 <1429672640.14162.55.camel@mtksdaap41>
Message-ID: <20150430201207.GK22845@sirena.org.uk>

On Wed, Apr 22, 2015 at 11:17:20AM +0800, Koro Chen wrote:

> If using DPCM, it seems the most suitable FE DAIs will be memif, and
> external interface like I2S should be BE DAIs. Do you think it is
> suitable for our memif to be FE DAIs? Then which memif to used can be
> described in a machine driver's FE DAIs. But I think this has a problem
> that our memif is one-direction, playback or capture. So the binded pcm
> device cannot have playback and capture capability together. May it
> cause trouble for user space apps that assumes there will be pcmC0D0p,
> pcmC0D0c?

I think the only userspace application you really have to worry about
here is PulseAudio which (at least with UCM) should be able to cope
since it needs to handle things like USB microphones.  I think
everything else I can think of can either cope or has to handle the same
use cases as PulseAudio does so should have support.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20150430/243c1ad7/attachment.sig>

From sboyd at codeaurora.org  Thu Apr 30 18:20:39 2015
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Thu, 30 Apr 2015 18:20:39 -0700
Subject: [PATCH 6/6] dt-bindings: ARM: Mediatek: Document devicetree
 bindings for clock/reset controllers
In-Reply-To: <1429778143-2074-7-git-send-email-s.hauer@pengutronix.de>
References: <1429778143-2074-1-git-send-email-s.hauer@pengutronix.de>
 <1429778143-2074-7-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150501012039.GG32407@codeaurora.org>

On 04/23, Sascha Hauer wrote:
> This adds the binding documentation for the apmixedsys, perisys and
> infracfg controllers found on Mediatek SoCs.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Please Cc devicetree reviewers on bindings (CCed now).

> ---
>  .../bindings/arm/mediatek/mediatek,apmixedsys.txt  | 23 +++++++++++++++++
>  .../bindings/arm/mediatek/mediatek,infracfg.txt    | 30 ++++++++++++++++++++++
>  .../bindings/arm/mediatek/mediatek,pericfg.txt     | 30 ++++++++++++++++++++++
>  .../bindings/arm/mediatek/mediatek,topckgen.txt    | 23 +++++++++++++++++
>  4 files changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> new file mode 100644
> index 0000000..5af6d73
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> @@ -0,0 +1,23 @@
> +Mediatek apmixedsys controller
> +==============================
> +
> +The Mediatek apmixedsys controller provides the PLLs to the system.
> +
> +Required Properties:
> +
> +- compatible: Should be:
> +	- "mediatek,mt8135-apmixedsys"
> +	- "mediatek,mt8173-apmixedsys"
> +- #clock-cells: Must be 1
> +
> +The apmixedsys controller uses the common clk binding from
> +Documentation/devicetree/bindings/clock/clock-bindings.txt
> +The available clocks are defined in dt-bindings/clock/mt*-clk.h.
> +
> +Example:
> +
> +apmixedsys: apmixedsys at 10209000 {

apmixedsys: clock-controller at 10209000 {

would be more standard. The same comment applies throughout this
patch. Otherwise it looks good to me.

-Stephen

> +	compatible = "mediatek,mt8173-apmixedsys";
> +	reg = <0 0x10209000 0 0x1000>;
> +	#clock-cells = <1>;
> +};
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
> new file mode 100644
> index 0000000..684da473
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
> @@ -0,0 +1,30 @@
> +Mediatek infracfg controller
> +============================
> +
> +The Mediatek infracfg controller provides various clocks and reset
> +outputs to the system.
> +
> +Required Properties:
> +
> +- compatible: Should be:
> +	- "mediatek,mt8135-infracfg", "syscon"
> +	- "mediatek,mt8173-infracfg", "syscon"
> +- #clock-cells: Must be 1
> +- #reset-cells: Must be 1
> +
> +The infracfg controller uses the common clk binding from
> +Documentation/devicetree/bindings/clock/clock-bindings.txt
> +The available clocks are defined in dt-bindings/clock/mt*-clk.h.
> +Also it uses the common reset controller binding from
> +Documentation/devicetree/bindings/reset/reset.txt.
> +The available reset outputs are defined in
> +dt-bindings/reset-controller/mt*-resets.h
> +
> +Example:
> +
> +infracfg: infracfg at 10001000 {
> +	compatible = "mediatek,mt8173-infracfg", "syscon";
> +	reg = <0 0x10001000 0 0x1000>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
> new file mode 100644
> index 0000000..fdb45c6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
> @@ -0,0 +1,30 @@
> +Mediatek pericfg controller
> +===========================
> +
> +The Mediatek pericfg controller provides various clocks and reset
> +outputs to the system.
> +
> +Required Properties:
> +
> +- compatible: Should be:
> +	- "mediatek,mt8135-pericfg", "syscon"
> +	- "mediatek,mt8173-pericfg", "syscon"
> +- #clock-cells: Must be 1
> +- #reset-cells: Must be 1
> +
> +The pericfg controller uses the common clk binding from
> +Documentation/devicetree/bindings/clock/clock-bindings.txt
> +The available clocks are defined in dt-bindings/clock/mt*-clk.h.
> +Also it uses the common reset controller binding from
> +Documentation/devicetree/bindings/reset/reset.txt.
> +The available reset outputs are defined in
> +dt-bindings/reset-controller/mt*-resets.h
> +
> +Example:
> +
> +pericfg: pericfg at 10003000 {
> +	compatible = "mediatek,mt8173-pericfg", "syscon";
> +	reg = <0 0x10003000 0 0x1000>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
> new file mode 100644
> index 0000000..a425248
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
> @@ -0,0 +1,23 @@
> +Mediatek topckgen controller
> +============================
> +
> +The Mediatek topckgen controller provides various clocks to the system.
> +
> +Required Properties:
> +
> +- compatible: Should be:
> +	- "mediatek,mt8135-topckgen"
> +	- "mediatek,mt8173-topckgen"
> +- #clock-cells: Must be 1
> +
> +The topckgen controller uses the common clk binding from
> +Documentation/devicetree/bindings/clock/clock-bindings.txt
> +The available clocks are defined in dt-bindings/clock/mt*-clk.h.
> +
> +Example:
> +
> +topckgen: topckgen at 10000000 {
> +	compatible = "mediatek,mt8173-topckgen";
> +	reg = <0 0x10000000 0 0x1000>;
> +	#clock-cells = <1>;
> +};
> -- 
> 2.1.4
> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From yingjoe.chen at mediatek.com  Thu Apr 30 23:49:30 2015
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Fri, 1 May 2015 14:49:30 +0800
Subject: [PATCH v2 1/2] ARM: dts: mt8135: Add pinctrl/GPIO/EINT node for
 mt8135.
Message-ID: <1430462971-28195-1-git-send-email-yingjoe.chen@mediatek.com>

From: Hongzhou Yang <hongzhou.yang at mediatek.com>

Patches based on v4.1-rc1. Change according to Matthias' suggestion.
- Remove comments on syscfg nodes
- Sort nodes by instance address & name.

---8<--------------------------------------------------------------------
Add pinctrl,GPIO and EINT node to mt8135.dtsi.

Signed-off-by: Hongzhou Yang <hongzhou.yang at mediatek.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/boot/dts/mt8135-pinfunc.h | 1302 ++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/mt8135.dtsi      |   29 +
 2 files changed, 1331 insertions(+)
 create mode 100644 arch/arm/boot/dts/mt8135-pinfunc.h

diff --git a/arch/arm/boot/dts/mt8135-pinfunc.h b/arch/arm/boot/dts/mt8135-pinfunc.h
new file mode 100644
index 0000000..5a60987
--- /dev/null
+++ b/arch/arm/boot/dts/mt8135-pinfunc.h
@@ -0,0 +1,1302 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang at mediatek.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.
+ */
+
+#ifndef __DTS_MT8135_PINFUNC_H
+#define __DTS_MT8135_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(0) | 1)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_EINT49 (MTK_PIN_NO(0) | 2)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_I2SOUT_DAT (MTK_PIN_NO(0) | 3)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_DAC_DAT_OUT (MTK_PIN_NO(0) | 4)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_PCM1_DO (MTK_PIN_NO(0) | 5)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_SPI1_MO (MTK_PIN_NO(0) | 6)
+#define MT8135_PIN_0_MSDC0_DAT7__FUNC_NALE (MTK_PIN_NO(0) | 7)
+
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(1) | 1)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_EINT48 (MTK_PIN_NO(1) | 2)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_I2SIN_WS (MTK_PIN_NO(1) | 3)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_DAC_WS (MTK_PIN_NO(1) | 4)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_PCM1_WS (MTK_PIN_NO(1) | 5)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_SPI1_CSN (MTK_PIN_NO(1) | 6)
+#define MT8135_PIN_1_MSDC0_DAT6__FUNC_NCLE (MTK_PIN_NO(1) | 7)
+
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(2) | 1)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_EINT47 (MTK_PIN_NO(2) | 2)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_I2SIN_CK (MTK_PIN_NO(2) | 3)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_DAC_CK (MTK_PIN_NO(2) | 4)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_PCM1_CK (MTK_PIN_NO(2) | 5)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_SPI1_CLK (MTK_PIN_NO(2) | 6)
+#define MT8135_PIN_2_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(2) | 7)
+
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(3) | 1)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_EINT46 (MTK_PIN_NO(3) | 2)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_A_FUNC_CK (MTK_PIN_NO(3) | 3)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_LSCE1B_2X (MTK_PIN_NO(3) | 6)
+#define MT8135_PIN_3_MSDC0_DAT4__FUNC_NLD5 (MTK_PIN_NO(3) | 7)
+
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(4) | 1)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_EINT41 (MTK_PIN_NO(4) | 2)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_A_FUNC_DOUT_0 (MTK_PIN_NO(4) | 3)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_USB_TEST_IO_0 (MTK_PIN_NO(4) | 5)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_LRSTB_2X (MTK_PIN_NO(4) | 6)
+#define MT8135_PIN_4_MSDC0_CMD__FUNC_NRNB (MTK_PIN_NO(4) | 7)
+
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(5) | 1)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_EINT40 (MTK_PIN_NO(5) | 2)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_A_FUNC_DOUT_1 (MTK_PIN_NO(5) | 3)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_USB_TEST_IO_1 (MTK_PIN_NO(5) | 5)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_LPTE (MTK_PIN_NO(5) | 6)
+#define MT8135_PIN_5_MSDC0_CLK__FUNC_NREB (MTK_PIN_NO(5) | 7)
+
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(6) | 1)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_EINT45 (MTK_PIN_NO(6) | 2)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_A_FUNC_DOUT_2 (MTK_PIN_NO(6) | 3)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_USB_TEST_IO_2 (MTK_PIN_NO(6) | 5)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_LSCE0B_2X (MTK_PIN_NO(6) | 6)
+#define MT8135_PIN_6_MSDC0_DAT3__FUNC_NLD7 (MTK_PIN_NO(6) | 7)
+
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(7) | 1)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_EINT44 (MTK_PIN_NO(7) | 2)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_A_FUNC_DOUT_3 (MTK_PIN_NO(7) | 3)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_USB_TEST_IO_3 (MTK_PIN_NO(7) | 5)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_LSA0_2X (MTK_PIN_NO(7) | 6)
+#define MT8135_PIN_7_MSDC0_DAT2__FUNC_NLD14 (MTK_PIN_NO(7) | 7)
+
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(8) | 1)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_EINT43 (MTK_PIN_NO(8) | 2)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_USB_TEST_IO_4 (MTK_PIN_NO(8) | 5)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_LSCK_2X (MTK_PIN_NO(8) | 6)
+#define MT8135_PIN_8_MSDC0_DAT1__FUNC_NLD11 (MTK_PIN_NO(8) | 7)
+
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(9) | 1)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_EINT42 (MTK_PIN_NO(9) | 2)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_USB_TEST_IO_5 (MTK_PIN_NO(9) | 5)
+#define MT8135_PIN_9_MSDC0_DAT0__FUNC_LSDA_2X (MTK_PIN_NO(9) | 6)
+
+#define MT8135_PIN_10_NCEB0__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT8135_PIN_10_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(10) | 1)
+#define MT8135_PIN_10_NCEB0__FUNC_EINT139 (MTK_PIN_NO(10) | 2)
+#define MT8135_PIN_10_NCEB0__FUNC_TESTA_OUT4 (MTK_PIN_NO(10) | 7)
+
+#define MT8135_PIN_11_NCEB1__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT8135_PIN_11_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(11) | 1)
+#define MT8135_PIN_11_NCEB1__FUNC_EINT140 (MTK_PIN_NO(11) | 2)
+#define MT8135_PIN_11_NCEB1__FUNC_USB_DRVVBUS (MTK_PIN_NO(11) | 6)
+#define MT8135_PIN_11_NCEB1__FUNC_TESTA_OUT5 (MTK_PIN_NO(11) | 7)
+
+#define MT8135_PIN_12_NRNB__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT8135_PIN_12_NRNB__FUNC_NRNB (MTK_PIN_NO(12) | 1)
+#define MT8135_PIN_12_NRNB__FUNC_EINT141 (MTK_PIN_NO(12) | 2)
+#define MT8135_PIN_12_NRNB__FUNC_A_FUNC_DOUT_4 (MTK_PIN_NO(12) | 3)
+#define MT8135_PIN_12_NRNB__FUNC_TESTA_OUT6 (MTK_PIN_NO(12) | 7)
+
+#define MT8135_PIN_13_NCLE__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT8135_PIN_13_NCLE__FUNC_NCLE (MTK_PIN_NO(13) | 1)
+#define MT8135_PIN_13_NCLE__FUNC_EINT142 (MTK_PIN_NO(13) | 2)
+#define MT8135_PIN_13_NCLE__FUNC_A_FUNC_DOUT_5 (MTK_PIN_NO(13) | 3)
+#define MT8135_PIN_13_NCLE__FUNC_CM2PDN_1X (MTK_PIN_NO(13) | 4)
+#define MT8135_PIN_13_NCLE__FUNC_NALE (MTK_PIN_NO(13) | 6)
+#define MT8135_PIN_13_NCLE__FUNC_TESTA_OUT7 (MTK_PIN_NO(13) | 7)
+
+#define MT8135_PIN_14_NALE__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT8135_PIN_14_NALE__FUNC_NALE (MTK_PIN_NO(14) | 1)
+#define MT8135_PIN_14_NALE__FUNC_EINT143 (MTK_PIN_NO(14) | 2)
+#define MT8135_PIN_14_NALE__FUNC_A_FUNC_DOUT_6 (MTK_PIN_NO(14) | 3)
+#define MT8135_PIN_14_NALE__FUNC_CM2MCLK_1X (MTK_PIN_NO(14) | 4)
+#define MT8135_PIN_14_NALE__FUNC_IRDA_RXD (MTK_PIN_NO(14) | 5)
+#define MT8135_PIN_14_NALE__FUNC_NCLE (MTK_PIN_NO(14) | 6)
+#define MT8135_PIN_14_NALE__FUNC_TESTA_OUT8 (MTK_PIN_NO(14) | 7)
+
+#define MT8135_PIN_15_NREB__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT8135_PIN_15_NREB__FUNC_NREB (MTK_PIN_NO(15) | 1)
+#define MT8135_PIN_15_NREB__FUNC_EINT144 (MTK_PIN_NO(15) | 2)
+#define MT8135_PIN_15_NREB__FUNC_A_FUNC_DOUT_7 (MTK_PIN_NO(15) | 3)
+#define MT8135_PIN_15_NREB__FUNC_CM2RST_1X (MTK_PIN_NO(15) | 4)
+#define MT8135_PIN_15_NREB__FUNC_IRDA_TXD (MTK_PIN_NO(15) | 5)
+#define MT8135_PIN_15_NREB__FUNC_TESTA_OUT9 (MTK_PIN_NO(15) | 7)
+
+#define MT8135_PIN_16_NWEB__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define MT8135_PIN_16_NWEB__FUNC_NWEB (MTK_PIN_NO(16) | 1)
+#define MT8135_PIN_16_NWEB__FUNC_EINT145 (MTK_PIN_NO(16) | 2)
+#define MT8135_PIN_16_NWEB__FUNC_A_FUNC_DIN_0 (MTK_PIN_NO(16) | 3)
+#define MT8135_PIN_16_NWEB__FUNC_CM2PCLK_1X (MTK_PIN_NO(16) | 4)
+#define MT8135_PIN_16_NWEB__FUNC_IRDA_PDN (MTK_PIN_NO(16) | 5)
+#define MT8135_PIN_16_NWEB__FUNC_TESTA_OUT10 (MTK_PIN_NO(16) | 7)
+
+#define MT8135_PIN_17_NLD0__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define MT8135_PIN_17_NLD0__FUNC_NLD0 (MTK_PIN_NO(17) | 1)
+#define MT8135_PIN_17_NLD0__FUNC_EINT146 (MTK_PIN_NO(17) | 2)
+#define MT8135_PIN_17_NLD0__FUNC_A_FUNC_DIN_1 (MTK_PIN_NO(17) | 3)
+#define MT8135_PIN_17_NLD0__FUNC_CM2DAT_1X_0 (MTK_PIN_NO(17) | 4)
+#define MT8135_PIN_17_NLD0__FUNC_I2SIN_CK (MTK_PIN_NO(17) | 5)
+#define MT8135_PIN_17_NLD0__FUNC_DAC_CK (MTK_PIN_NO(17) | 6)
+#define MT8135_PIN_17_NLD0__FUNC_TESTA_OUT11 (MTK_PIN_NO(17) | 7)
+
+#define MT8135_PIN_18_NLD1__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT8135_PIN_18_NLD1__FUNC_NLD1 (MTK_PIN_NO(18) | 1)
+#define MT8135_PIN_18_NLD1__FUNC_EINT147 (MTK_PIN_NO(18) | 2)
+#define MT8135_PIN_18_NLD1__FUNC_A_FUNC_DIN_2 (MTK_PIN_NO(18) | 3)
+#define MT8135_PIN_18_NLD1__FUNC_CM2DAT_1X_1 (MTK_PIN_NO(18) | 4)
+#define MT8135_PIN_18_NLD1__FUNC_I2SIN_WS (MTK_PIN_NO(18) | 5)
+#define MT8135_PIN_18_NLD1__FUNC_DAC_WS (MTK_PIN_NO(18) | 6)
+#define MT8135_PIN_18_NLD1__FUNC_TESTA_OUT12 (MTK_PIN_NO(18) | 7)
+
+#define MT8135_PIN_19_NLD2__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT8135_PIN_19_NLD2__FUNC_NLD2 (MTK_PIN_NO(19) | 1)
+#define MT8135_PIN_19_NLD2__FUNC_EINT148 (MTK_PIN_NO(19) | 2)
+#define MT8135_PIN_19_NLD2__FUNC_A_FUNC_DIN_3 (MTK_PIN_NO(19) | 3)
+#define MT8135_PIN_19_NLD2__FUNC_CM2DAT_1X_2 (MTK_PIN_NO(19) | 4)
+#define MT8135_PIN_19_NLD2__FUNC_I2SOUT_DAT (MTK_PIN_NO(19) | 5)
+#define MT8135_PIN_19_NLD2__FUNC_DAC_DAT_OUT (MTK_PIN_NO(19) | 6)
+#define MT8135_PIN_19_NLD2__FUNC_TESTA_OUT13 (MTK_PIN_NO(19) | 7)
+
+#define MT8135_PIN_20_NLD3__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT8135_PIN_20_NLD3__FUNC_NLD3 (MTK_PIN_NO(20) | 1)
+#define MT8135_PIN_20_NLD3__FUNC_EINT149 (MTK_PIN_NO(20) | 2)
+#define MT8135_PIN_20_NLD3__FUNC_A_FUNC_DIN_4 (MTK_PIN_NO(20) | 3)
+#define MT8135_PIN_20_NLD3__FUNC_CM2DAT_1X_3 (MTK_PIN_NO(20) | 4)
+#define MT8135_PIN_20_NLD3__FUNC_TESTA_OUT14 (MTK_PIN_NO(20) | 7)
+
+#define MT8135_PIN_21_NLD4__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT8135_PIN_21_NLD4__FUNC_NLD4 (MTK_PIN_NO(21) | 1)
+#define MT8135_PIN_21_NLD4__FUNC_EINT150 (MTK_PIN_NO(21) | 2)
+#define MT8135_PIN_21_NLD4__FUNC_A_FUNC_DIN_5 (MTK_PIN_NO(21) | 3)
+#define MT8135_PIN_21_NLD4__FUNC_CM2DAT_1X_4 (MTK_PIN_NO(21) | 4)
+#define MT8135_PIN_21_NLD4__FUNC_TESTA_OUT15 (MTK_PIN_NO(21) | 7)
+
+#define MT8135_PIN_22_NLD5__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT8135_PIN_22_NLD5__FUNC_NLD5 (MTK_PIN_NO(22) | 1)
+#define MT8135_PIN_22_NLD5__FUNC_EINT151 (MTK_PIN_NO(22) | 2)
+#define MT8135_PIN_22_NLD5__FUNC_A_FUNC_DIN_6 (MTK_PIN_NO(22) | 3)
+#define MT8135_PIN_22_NLD5__FUNC_CM2DAT_1X_5 (MTK_PIN_NO(22) | 4)
+#define MT8135_PIN_22_NLD5__FUNC_TESTA_OUT16 (MTK_PIN_NO(22) | 7)
+
+#define MT8135_PIN_23_NLD6__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT8135_PIN_23_NLD6__FUNC_NLD6 (MTK_PIN_NO(23) | 1)
+#define MT8135_PIN_23_NLD6__FUNC_EINT152 (MTK_PIN_NO(23) | 2)
+#define MT8135_PIN_23_NLD6__FUNC_A_FUNC_DIN_7 (MTK_PIN_NO(23) | 3)
+#define MT8135_PIN_23_NLD6__FUNC_CM2DAT_1X_6 (MTK_PIN_NO(23) | 4)
+#define MT8135_PIN_23_NLD6__FUNC_TESTA_OUT17 (MTK_PIN_NO(23) | 7)
+
+#define MT8135_PIN_24_NLD7__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT8135_PIN_24_NLD7__FUNC_NLD7 (MTK_PIN_NO(24) | 1)
+#define MT8135_PIN_24_NLD7__FUNC_EINT153 (MTK_PIN_NO(24) | 2)
+#define MT8135_PIN_24_NLD7__FUNC_A_FUNC_DIN_8 (MTK_PIN_NO(24) | 3)
+#define MT8135_PIN_24_NLD7__FUNC_CM2DAT_1X_7 (MTK_PIN_NO(24) | 4)
+#define MT8135_PIN_24_NLD7__FUNC_TESTA_OUT18 (MTK_PIN_NO(24) | 7)
+
+#define MT8135_PIN_25_NLD8__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT8135_PIN_25_NLD8__FUNC_NLD8 (MTK_PIN_NO(25) | 1)
+#define MT8135_PIN_25_NLD8__FUNC_EINT154 (MTK_PIN_NO(25) | 2)
+#define MT8135_PIN_25_NLD8__FUNC_CM2DAT_1X_8 (MTK_PIN_NO(25) | 4)
+
+#define MT8135_PIN_26_NLD9__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT8135_PIN_26_NLD9__FUNC_NLD9 (MTK_PIN_NO(26) | 1)
+#define MT8135_PIN_26_NLD9__FUNC_EINT155 (MTK_PIN_NO(26) | 2)
+#define MT8135_PIN_26_NLD9__FUNC_CM2DAT_1X_9 (MTK_PIN_NO(26) | 4)
+#define MT8135_PIN_26_NLD9__FUNC_PWM1 (MTK_PIN_NO(26) | 5)
+
+#define MT8135_PIN_27_NLD10__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT8135_PIN_27_NLD10__FUNC_NLD10 (MTK_PIN_NO(27) | 1)
+#define MT8135_PIN_27_NLD10__FUNC_EINT156 (MTK_PIN_NO(27) | 2)
+#define MT8135_PIN_27_NLD10__FUNC_CM2VSYNC_1X (MTK_PIN_NO(27) | 4)
+#define MT8135_PIN_27_NLD10__FUNC_PWM2 (MTK_PIN_NO(27) | 5)
+
+#define MT8135_PIN_28_NLD11__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT8135_PIN_28_NLD11__FUNC_NLD11 (MTK_PIN_NO(28) | 1)
+#define MT8135_PIN_28_NLD11__FUNC_EINT157 (MTK_PIN_NO(28) | 2)
+#define MT8135_PIN_28_NLD11__FUNC_CM2HSYNC_1X (MTK_PIN_NO(28) | 4)
+#define MT8135_PIN_28_NLD11__FUNC_PWM3 (MTK_PIN_NO(28) | 5)
+
+#define MT8135_PIN_29_NLD12__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT8135_PIN_29_NLD12__FUNC_NLD12 (MTK_PIN_NO(29) | 1)
+#define MT8135_PIN_29_NLD12__FUNC_EINT158 (MTK_PIN_NO(29) | 2)
+#define MT8135_PIN_29_NLD12__FUNC_I2SIN_CK (MTK_PIN_NO(29) | 3)
+#define MT8135_PIN_29_NLD12__FUNC_DAC_CK (MTK_PIN_NO(29) | 4)
+#define MT8135_PIN_29_NLD12__FUNC_PCM1_CK (MTK_PIN_NO(29) | 5)
+
+#define MT8135_PIN_30_NLD13__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define MT8135_PIN_30_NLD13__FUNC_NLD13 (MTK_PIN_NO(30) | 1)
+#define MT8135_PIN_30_NLD13__FUNC_EINT159 (MTK_PIN_NO(30) | 2)
+#define MT8135_PIN_30_NLD13__FUNC_I2SIN_WS (MTK_PIN_NO(30) | 3)
+#define MT8135_PIN_30_NLD13__FUNC_DAC_WS (MTK_PIN_NO(30) | 4)
+#define MT8135_PIN_30_NLD13__FUNC_PCM1_WS (MTK_PIN_NO(30) | 5)
+
+#define MT8135_PIN_31_NLD14__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define MT8135_PIN_31_NLD14__FUNC_NLD14 (MTK_PIN_NO(31) | 1)
+#define MT8135_PIN_31_NLD14__FUNC_EINT160 (MTK_PIN_NO(31) | 2)
+#define MT8135_PIN_31_NLD14__FUNC_I2SOUT_DAT (MTK_PIN_NO(31) | 3)
+#define MT8135_PIN_31_NLD14__FUNC_DAC_DAT_OUT (MTK_PIN_NO(31) | 4)
+#define MT8135_PIN_31_NLD14__FUNC_PCM1_DO (MTK_PIN_NO(31) | 5)
+
+#define MT8135_PIN_32_NLD15__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define MT8135_PIN_32_NLD15__FUNC_NLD15 (MTK_PIN_NO(32) | 1)
+#define MT8135_PIN_32_NLD15__FUNC_EINT161 (MTK_PIN_NO(32) | 2)
+#define MT8135_PIN_32_NLD15__FUNC_DISP_PWM (MTK_PIN_NO(32) | 3)
+#define MT8135_PIN_32_NLD15__FUNC_PWM4 (MTK_PIN_NO(32) | 4)
+#define MT8135_PIN_32_NLD15__FUNC_PCM1_DI (MTK_PIN_NO(32) | 5)
+
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(33) | 1)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_EINT50 (MTK_PIN_NO(33) | 2)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_I2SIN_DAT (MTK_PIN_NO(33) | 3)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_PCM1_DI (MTK_PIN_NO(33) | 5)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_SPI1_MI (MTK_PIN_NO(33) | 6)
+#define MT8135_PIN_33_MSDC0_RSTB__FUNC_NLD10 (MTK_PIN_NO(33) | 7)
+
+#define MT8135_PIN_34_IDDIG__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT8135_PIN_34_IDDIG__FUNC_IDDIG (MTK_PIN_NO(34) | 1)
+#define MT8135_PIN_34_IDDIG__FUNC_EINT34 (MTK_PIN_NO(34) | 2)
+
+#define MT8135_PIN_35_SCL3__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT8135_PIN_35_SCL3__FUNC_SCL3 (MTK_PIN_NO(35) | 1)
+#define MT8135_PIN_35_SCL3__FUNC_EINT96 (MTK_PIN_NO(35) | 2)
+#define MT8135_PIN_35_SCL3__FUNC_CLKM6 (MTK_PIN_NO(35) | 3)
+#define MT8135_PIN_35_SCL3__FUNC_PWM6 (MTK_PIN_NO(35) | 4)
+
+#define MT8135_PIN_36_SDA3__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT8135_PIN_36_SDA3__FUNC_SDA3 (MTK_PIN_NO(36) | 1)
+#define MT8135_PIN_36_SDA3__FUNC_EINT97 (MTK_PIN_NO(36) | 2)
+
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(37) | 1)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_ADC_CK (MTK_PIN_NO(37) | 2)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_HDMI_SDATA0 (MTK_PIN_NO(37) | 3)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_EINT19 (MTK_PIN_NO(37) | 4)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_USB_TEST_IO_6 (MTK_PIN_NO(37) | 5)
+#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_TESTA_OUT19 (MTK_PIN_NO(37) | 7)
+
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(38) | 1)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_ADC_WS (MTK_PIN_NO(38) | 2)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MISO (MTK_PIN_NO(38) | 3)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_EINT21 (MTK_PIN_NO(38) | 4)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_USB_TEST_IO_7 (MTK_PIN_NO(38) | 5)
+#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_TESTA_OUT20 (MTK_PIN_NO(38) | 7)
+
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MISO (MTK_PIN_NO(39) | 1)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_ADC_DAT_IN (MTK_PIN_NO(39) | 2)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(39) | 3)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_EINT20 (MTK_PIN_NO(39) | 4)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_USB_TEST_IO_8 (MTK_PIN_NO(39) | 5)
+#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_TESTA_OUT21 (MTK_PIN_NO(39) | 7)
+
+#define MT8135_PIN_40_DAC_CLK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT8135_PIN_40_DAC_CLK__FUNC_DAC_CK (MTK_PIN_NO(40) | 1)
+#define MT8135_PIN_40_DAC_CLK__FUNC_EINT22 (MTK_PIN_NO(40) | 2)
+#define MT8135_PIN_40_DAC_CLK__FUNC_HDMI_SDATA1 (MTK_PIN_NO(40) | 3)
+#define MT8135_PIN_40_DAC_CLK__FUNC_USB_TEST_IO_9 (MTK_PIN_NO(40) | 5)
+#define MT8135_PIN_40_DAC_CLK__FUNC_TESTA_OUT22 (MTK_PIN_NO(40) | 7)
+
+#define MT8135_PIN_41_DAC_WS__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT8135_PIN_41_DAC_WS__FUNC_DAC_WS (MTK_PIN_NO(41) | 1)
+#define MT8135_PIN_41_DAC_WS__FUNC_EINT24 (MTK_PIN_NO(41) | 2)
+#define MT8135_PIN_41_DAC_WS__FUNC_HDMI_SDATA2 (MTK_PIN_NO(41) | 3)
+#define MT8135_PIN_41_DAC_WS__FUNC_USB_TEST_IO_10 (MTK_PIN_NO(41) | 5)
+#define MT8135_PIN_41_DAC_WS__FUNC_TESTA_OUT23 (MTK_PIN_NO(41) | 7)
+
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(42) | 1)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_EINT23 (MTK_PIN_NO(42) | 2)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_HDMI_SDATA3 (MTK_PIN_NO(42) | 3)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_USB_TEST_IO_11 (MTK_PIN_NO(42) | 5)
+#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_TESTA_OUT24 (MTK_PIN_NO(42) | 7)
+
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(43) | 1)
+#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_EINT29 (MTK_PIN_NO(43) | 2)
+
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(44) | 1)
+#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_EINT28 (MTK_PIN_NO(44) | 2)
+
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(45) | 1)
+#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_EINT27 (MTK_PIN_NO(45) | 2)
+
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(46) | 1)
+#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_EINT26 (MTK_PIN_NO(46) | 2)
+
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_PWRAP_EVENT_IN (MTK_PIN_NO(47) | 1)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_EINT25 (MTK_PIN_NO(47) | 2)
+#define MT8135_PIN_47_PWRAP_EVENT__FUNC_TESTA_OUT2 (MTK_PIN_NO(47) | 7)
+
+#define MT8135_PIN_48_RTC32K_CK__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT8135_PIN_48_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(48) | 1)
+
+#define MT8135_PIN_49_WATCHDOG__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT8135_PIN_49_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(49) | 1)
+#define MT8135_PIN_49_WATCHDOG__FUNC_EINT36 (MTK_PIN_NO(49) | 2)
+
+#define MT8135_PIN_50_SRCLKENA__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define MT8135_PIN_50_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(50) | 1)
+#define MT8135_PIN_50_SRCLKENA__FUNC_EINT38 (MTK_PIN_NO(50) | 2)
+
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_SRCVOLTEN (MTK_PIN_NO(51) | 1)
+#define MT8135_PIN_51_SRCVOLTEN__FUNC_EINT37 (MTK_PIN_NO(51) | 2)
+
+#define MT8135_PIN_52_EINT0__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define MT8135_PIN_52_EINT0__FUNC_EINT0 (MTK_PIN_NO(52) | 1)
+#define MT8135_PIN_52_EINT0__FUNC_PWM1 (MTK_PIN_NO(52) | 2)
+#define MT8135_PIN_52_EINT0__FUNC_CLKM0 (MTK_PIN_NO(52) | 3)
+#define MT8135_PIN_52_EINT0__FUNC_SPDIF_OUT (MTK_PIN_NO(52) | 4)
+#define MT8135_PIN_52_EINT0__FUNC_USB_TEST_IO_12 (MTK_PIN_NO(52) | 5)
+#define MT8135_PIN_52_EINT0__FUNC_USB_SCL (MTK_PIN_NO(52) | 7)
+
+#define MT8135_PIN_53_URXD2__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT8135_PIN_53_URXD2__FUNC_URXD2 (MTK_PIN_NO(53) | 1)
+#define MT8135_PIN_53_URXD2__FUNC_EINT83 (MTK_PIN_NO(53) | 2)
+#define MT8135_PIN_53_URXD2__FUNC_HDMI_LRCK (MTK_PIN_NO(53) | 4)
+#define MT8135_PIN_53_URXD2__FUNC_CLKM3 (MTK_PIN_NO(53) | 5)
+#define MT8135_PIN_53_URXD2__FUNC_UTXD2 (MTK_PIN_NO(53) | 7)
+
+#define MT8135_PIN_54_UTXD2__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT8135_PIN_54_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(54) | 1)
+#define MT8135_PIN_54_UTXD2__FUNC_EINT82 (MTK_PIN_NO(54) | 2)
+#define MT8135_PIN_54_UTXD2__FUNC_HDMI_BCK_OUT (MTK_PIN_NO(54) | 4)
+#define MT8135_PIN_54_UTXD2__FUNC_CLKM2 (MTK_PIN_NO(54) | 5)
+#define MT8135_PIN_54_UTXD2__FUNC_URXD2 (MTK_PIN_NO(54) | 7)
+
+#define MT8135_PIN_55_UCTS2__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT8135_PIN_55_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(55) | 1)
+#define MT8135_PIN_55_UCTS2__FUNC_EINT84 (MTK_PIN_NO(55) | 2)
+#define MT8135_PIN_55_UCTS2__FUNC_PWM1 (MTK_PIN_NO(55) | 5)
+#define MT8135_PIN_55_UCTS2__FUNC_URTS2 (MTK_PIN_NO(55) | 7)
+
+#define MT8135_PIN_56_URTS2__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT8135_PIN_56_URTS2__FUNC_URTS2 (MTK_PIN_NO(56) | 1)
+#define MT8135_PIN_56_URTS2__FUNC_EINT85 (MTK_PIN_NO(56) | 2)
+#define MT8135_PIN_56_URTS2__FUNC_PWM2 (MTK_PIN_NO(56) | 5)
+#define MT8135_PIN_56_URTS2__FUNC_UCTS2 (MTK_PIN_NO(56) | 7)
+
+#define MT8135_PIN_57_JTCK__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define MT8135_PIN_57_JTCK__FUNC_JTCK (MTK_PIN_NO(57) | 1)
+#define MT8135_PIN_57_JTCK__FUNC_EINT188 (MTK_PIN_NO(57) | 2)
+#define MT8135_PIN_57_JTCK__FUNC_DSP1_ICK (MTK_PIN_NO(57) | 3)
+
+#define MT8135_PIN_58_JTDO__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define MT8135_PIN_58_JTDO__FUNC_JTDO (MTK_PIN_NO(58) | 1)
+#define MT8135_PIN_58_JTDO__FUNC_EINT190 (MTK_PIN_NO(58) | 2)
+#define MT8135_PIN_58_JTDO__FUNC_DSP2_IMS (MTK_PIN_NO(58) | 3)
+
+#define MT8135_PIN_59_JTRST_B__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define MT8135_PIN_59_JTRST_B__FUNC_JTRST_B (MTK_PIN_NO(59) | 1)
+#define MT8135_PIN_59_JTRST_B__FUNC_EINT0 (MTK_PIN_NO(59) | 2)
+#define MT8135_PIN_59_JTRST_B__FUNC_DSP2_ICK (MTK_PIN_NO(59) | 3)
+
+#define MT8135_PIN_60_JTDI__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define MT8135_PIN_60_JTDI__FUNC_JTDI (MTK_PIN_NO(60) | 1)
+#define MT8135_PIN_60_JTDI__FUNC_EINT189 (MTK_PIN_NO(60) | 2)
+#define MT8135_PIN_60_JTDI__FUNC_DSP1_IMS (MTK_PIN_NO(60) | 3)
+
+#define MT8135_PIN_61_JRTCK__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define MT8135_PIN_61_JRTCK__FUNC_JRTCK (MTK_PIN_NO(61) | 1)
+#define MT8135_PIN_61_JRTCK__FUNC_EINT187 (MTK_PIN_NO(61) | 2)
+#define MT8135_PIN_61_JRTCK__FUNC_DSP1_ID (MTK_PIN_NO(61) | 3)
+
+#define MT8135_PIN_62_JTMS__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define MT8135_PIN_62_JTMS__FUNC_JTMS (MTK_PIN_NO(62) | 1)
+#define MT8135_PIN_62_JTMS__FUNC_EINT191 (MTK_PIN_NO(62) | 2)
+#define MT8135_PIN_62_JTMS__FUNC_DSP2_ID (MTK_PIN_NO(62) | 3)
+
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_MSDC1_INSI (MTK_PIN_NO(63) | 1)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_SCL5 (MTK_PIN_NO(63) | 3)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_PWM6 (MTK_PIN_NO(63) | 4)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_CLKM5 (MTK_PIN_NO(63) | 5)
+#define MT8135_PIN_63_MSDC1_INSI__FUNC_TESTB_OUT6 (MTK_PIN_NO(63) | 7)
+
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_MSDC1_SDWPI (MTK_PIN_NO(64) | 1)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_EINT58 (MTK_PIN_NO(64) | 2)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_SDA5 (MTK_PIN_NO(64) | 3)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_PWM7 (MTK_PIN_NO(64) | 4)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_CLKM6 (MTK_PIN_NO(64) | 5)
+#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_TESTB_OUT7 (MTK_PIN_NO(64) | 7)
+
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_MSDC2_INSI (MTK_PIN_NO(65) | 1)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_USB_TEST_IO_27 (MTK_PIN_NO(65) | 5)
+#define MT8135_PIN_65_MSDC2_INSI__FUNC_TESTA_OUT3 (MTK_PIN_NO(65) | 7)
+
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_MSDC2_SDWPI (MTK_PIN_NO(66) | 1)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_EINT66 (MTK_PIN_NO(66) | 2)
+#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_USB_TEST_IO_28 (MTK_PIN_NO(66) | 5)
+
+#define MT8135_PIN_67_URXD4__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define MT8135_PIN_67_URXD4__FUNC_URXD4 (MTK_PIN_NO(67) | 1)
+#define MT8135_PIN_67_URXD4__FUNC_EINT89 (MTK_PIN_NO(67) | 2)
+#define MT8135_PIN_67_URXD4__FUNC_URXD1 (MTK_PIN_NO(67) | 3)
+#define MT8135_PIN_67_URXD4__FUNC_UTXD4 (MTK_PIN_NO(67) | 6)
+#define MT8135_PIN_67_URXD4__FUNC_TESTB_OUT10 (MTK_PIN_NO(67) | 7)
+
+#define MT8135_PIN_68_UTXD4__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define MT8135_PIN_68_UTXD4__FUNC_UTXD4 (MTK_PIN_NO(68) | 1)
+#define MT8135_PIN_68_UTXD4__FUNC_EINT88 (MTK_PIN_NO(68) | 2)
+#define MT8135_PIN_68_UTXD4__FUNC_UTXD1 (MTK_PIN_NO(68) | 3)
+#define MT8135_PIN_68_UTXD4__FUNC_URXD4 (MTK_PIN_NO(68) | 6)
+#define MT8135_PIN_68_UTXD4__FUNC_TESTB_OUT11 (MTK_PIN_NO(68) | 7)
+
+#define MT8135_PIN_69_URXD1__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define MT8135_PIN_69_URXD1__FUNC_URXD1 (MTK_PIN_NO(69) | 1)
+#define MT8135_PIN_69_URXD1__FUNC_EINT79 (MTK_PIN_NO(69) | 2)
+#define MT8135_PIN_69_URXD1__FUNC_URXD4 (MTK_PIN_NO(69) | 3)
+#define MT8135_PIN_69_URXD1__FUNC_UTXD1 (MTK_PIN_NO(69) | 6)
+#define MT8135_PIN_69_URXD1__FUNC_TESTB_OUT24 (MTK_PIN_NO(69) | 7)
+
+#define MT8135_PIN_70_UTXD1__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define MT8135_PIN_70_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(70) | 1)
+#define MT8135_PIN_70_UTXD1__FUNC_EINT78 (MTK_PIN_NO(70) | 2)
+#define MT8135_PIN_70_UTXD1__FUNC_UTXD4 (MTK_PIN_NO(70) | 3)
+#define MT8135_PIN_70_UTXD1__FUNC_URXD1 (MTK_PIN_NO(70) | 6)
+#define MT8135_PIN_70_UTXD1__FUNC_TESTB_OUT25 (MTK_PIN_NO(70) | 7)
+
+#define MT8135_PIN_71_UCTS1__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define MT8135_PIN_71_UCTS1__FUNC_UCTS1 (MTK_PIN_NO(71) | 1)
+#define MT8135_PIN_71_UCTS1__FUNC_EINT80 (MTK_PIN_NO(71) | 2)
+#define MT8135_PIN_71_UCTS1__FUNC_CLKM0 (MTK_PIN_NO(71) | 5)
+#define MT8135_PIN_71_UCTS1__FUNC_URTS1 (MTK_PIN_NO(71) | 6)
+#define MT8135_PIN_71_UCTS1__FUNC_TESTB_OUT31 (MTK_PIN_NO(71) | 7)
+
+#define MT8135_PIN_72_URTS1__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT8135_PIN_72_URTS1__FUNC_URTS1 (MTK_PIN_NO(72) | 1)
+#define MT8135_PIN_72_URTS1__FUNC_EINT81 (MTK_PIN_NO(72) | 2)
+#define MT8135_PIN_72_URTS1__FUNC_CLKM1 (MTK_PIN_NO(72) | 5)
+#define MT8135_PIN_72_URTS1__FUNC_UCTS1 (MTK_PIN_NO(72) | 6)
+#define MT8135_PIN_72_URTS1__FUNC_TESTB_OUT21 (MTK_PIN_NO(72) | 7)
+
+#define MT8135_PIN_73_PWM1__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT8135_PIN_73_PWM1__FUNC_PWM1 (MTK_PIN_NO(73) | 1)
+#define MT8135_PIN_73_PWM1__FUNC_EINT73 (MTK_PIN_NO(73) | 2)
+#define MT8135_PIN_73_PWM1__FUNC_USB_DRVVBUS (MTK_PIN_NO(73) | 5)
+#define MT8135_PIN_73_PWM1__FUNC_DISP_PWM (MTK_PIN_NO(73) | 6)
+#define MT8135_PIN_73_PWM1__FUNC_TESTB_OUT8 (MTK_PIN_NO(73) | 7)
+
+#define MT8135_PIN_74_PWM2__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT8135_PIN_74_PWM2__FUNC_PWM2 (MTK_PIN_NO(74) | 1)
+#define MT8135_PIN_74_PWM2__FUNC_EINT74 (MTK_PIN_NO(74) | 2)
+#define MT8135_PIN_74_PWM2__FUNC_DPI33_CK (MTK_PIN_NO(74) | 3)
+#define MT8135_PIN_74_PWM2__FUNC_PWM5 (MTK_PIN_NO(74) | 4)
+#define MT8135_PIN_74_PWM2__FUNC_URXD2 (MTK_PIN_NO(74) | 5)
+#define MT8135_PIN_74_PWM2__FUNC_DISP_PWM (MTK_PIN_NO(74) | 6)
+#define MT8135_PIN_74_PWM2__FUNC_TESTB_OUT9 (MTK_PIN_NO(74) | 7)
+
+#define MT8135_PIN_75_PWM3__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT8135_PIN_75_PWM3__FUNC_PWM3 (MTK_PIN_NO(75) | 1)
+#define MT8135_PIN_75_PWM3__FUNC_EINT75 (MTK_PIN_NO(75) | 2)
+#define MT8135_PIN_75_PWM3__FUNC_DPI33_D0 (MTK_PIN_NO(75) | 3)
+#define MT8135_PIN_75_PWM3__FUNC_PWM6 (MTK_PIN_NO(75) | 4)
+#define MT8135_PIN_75_PWM3__FUNC_UTXD2 (MTK_PIN_NO(75) | 5)
+#define MT8135_PIN_75_PWM3__FUNC_DISP_PWM (MTK_PIN_NO(75) | 6)
+#define MT8135_PIN_75_PWM3__FUNC_TESTB_OUT12 (MTK_PIN_NO(75) | 7)
+
+#define MT8135_PIN_76_PWM4__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT8135_PIN_76_PWM4__FUNC_PWM4 (MTK_PIN_NO(76) | 1)
+#define MT8135_PIN_76_PWM4__FUNC_EINT76 (MTK_PIN_NO(76) | 2)
+#define MT8135_PIN_76_PWM4__FUNC_DPI33_D1 (MTK_PIN_NO(76) | 3)
+#define MT8135_PIN_76_PWM4__FUNC_PWM7 (MTK_PIN_NO(76) | 4)
+#define MT8135_PIN_76_PWM4__FUNC_DISP_PWM (MTK_PIN_NO(76) | 6)
+#define MT8135_PIN_76_PWM4__FUNC_TESTB_OUT13 (MTK_PIN_NO(76) | 7)
+
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(77) | 1)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_EINT63 (MTK_PIN_NO(77) | 2)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DSP2_IMS (MTK_PIN_NO(77) | 4)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DPI33_D6 (MTK_PIN_NO(77) | 6)
+#define MT8135_PIN_77_MSDC2_DAT2__FUNC_TESTA_OUT25 (MTK_PIN_NO(77) | 7)
+
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(78) | 1)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_EINT64 (MTK_PIN_NO(78) | 2)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DSP2_ID (MTK_PIN_NO(78) | 4)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DPI33_D7 (MTK_PIN_NO(78) | 6)
+#define MT8135_PIN_78_MSDC2_DAT3__FUNC_TESTA_OUT26 (MTK_PIN_NO(78) | 7)
+
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(79) | 1)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_EINT60 (MTK_PIN_NO(79) | 2)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_DSP1_IMS (MTK_PIN_NO(79) | 4)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_PCM1_WS (MTK_PIN_NO(79) | 5)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_DPI33_D3 (MTK_PIN_NO(79) | 6)
+#define MT8135_PIN_79_MSDC2_CMD__FUNC_TESTA_OUT0 (MTK_PIN_NO(79) | 7)
+
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(80) | 1)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_EINT59 (MTK_PIN_NO(80) | 2)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_DSP1_ICK (MTK_PIN_NO(80) | 4)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_PCM1_CK (MTK_PIN_NO(80) | 5)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_DPI33_D2 (MTK_PIN_NO(80) | 6)
+#define MT8135_PIN_80_MSDC2_CLK__FUNC_TESTA_OUT1 (MTK_PIN_NO(80) | 7)
+
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(81) | 1)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_EINT62 (MTK_PIN_NO(81) | 2)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DSP2_ICK (MTK_PIN_NO(81) | 4)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_PCM1_DO (MTK_PIN_NO(81) | 5)
+#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DPI33_D5 (MTK_PIN_NO(81) | 6)
+
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(82) | 1)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_EINT61 (MTK_PIN_NO(82) | 2)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DSP1_ID (MTK_PIN_NO(82) | 4)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_PCM1_DI (MTK_PIN_NO(82) | 5)
+#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DPI33_D4 (MTK_PIN_NO(82) | 6)
+
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(83) | 1)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_EINT53 (MTK_PIN_NO(83) | 2)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_SCL1 (MTK_PIN_NO(83) | 3)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_PWM2 (MTK_PIN_NO(83) | 4)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_CLKM1 (MTK_PIN_NO(83) | 5)
+#define MT8135_PIN_83_MSDC1_DAT0__FUNC_TESTB_OUT2 (MTK_PIN_NO(83) | 7)
+
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(84) | 1)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_EINT54 (MTK_PIN_NO(84) | 2)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_SDA1 (MTK_PIN_NO(84) | 3)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_PWM3 (MTK_PIN_NO(84) | 4)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_CLKM2 (MTK_PIN_NO(84) | 5)
+#define MT8135_PIN_84_MSDC1_DAT1__FUNC_TESTB_OUT3 (MTK_PIN_NO(84) | 7)
+
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(85) | 1)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_EINT52 (MTK_PIN_NO(85) | 2)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_SDA0 (MTK_PIN_NO(85) | 3)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_PWM1 (MTK_PIN_NO(85) | 4)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_CLKM0 (MTK_PIN_NO(85) | 5)
+#define MT8135_PIN_85_MSDC1_CMD__FUNC_TESTB_OUT1 (MTK_PIN_NO(85) | 7)
+
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(86) | 1)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_EINT51 (MTK_PIN_NO(86) | 2)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_SCL0 (MTK_PIN_NO(86) | 3)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_DISP_PWM (MTK_PIN_NO(86) | 4)
+#define MT8135_PIN_86_MSDC1_CLK__FUNC_TESTB_OUT0 (MTK_PIN_NO(86) | 7)
+
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(87) | 1)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_EINT55 (MTK_PIN_NO(87) | 2)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_SCL4 (MTK_PIN_NO(87) | 3)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_PWM4 (MTK_PIN_NO(87) | 4)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_CLKM3 (MTK_PIN_NO(87) | 5)
+#define MT8135_PIN_87_MSDC1_DAT2__FUNC_TESTB_OUT4 (MTK_PIN_NO(87) | 7)
+
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(88) | 1)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_EINT56 (MTK_PIN_NO(88) | 2)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_SDA4 (MTK_PIN_NO(88) | 3)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_PWM5 (MTK_PIN_NO(88) | 4)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_CLKM4 (MTK_PIN_NO(88) | 5)
+#define MT8135_PIN_88_MSDC1_DAT3__FUNC_TESTB_OUT5 (MTK_PIN_NO(88) | 7)
+
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_MSDC4_DAT0 (MTK_PIN_NO(89) | 1)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EINT133 (MTK_PIN_NO(89) | 2)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(89) | 4)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_USB_DRVVBUS (MTK_PIN_NO(89) | 5)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_A_FUNC_DIN_9 (MTK_PIN_NO(89) | 6)
+#define MT8135_PIN_89_MSDC4_DAT0__FUNC_LPTE (MTK_PIN_NO(89) | 7)
+
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_MSDC4_DAT1 (MTK_PIN_NO(90) | 1)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_EINT134 (MTK_PIN_NO(90) | 2)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_A_FUNC_DIN_10 (MTK_PIN_NO(90) | 6)
+#define MT8135_PIN_90_MSDC4_DAT1__FUNC_LRSTB_1X (MTK_PIN_NO(90) | 7)
+
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_MSDC4_DAT5 (MTK_PIN_NO(91) | 1)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_EINT136 (MTK_PIN_NO(91) | 2)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_I2SIN_WS (MTK_PIN_NO(91) | 3)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_DAC_WS (MTK_PIN_NO(91) | 4)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_PCM1_WS (MTK_PIN_NO(91) | 5)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_A_FUNC_DIN_11 (MTK_PIN_NO(91) | 6)
+#define MT8135_PIN_91_MSDC4_DAT5__FUNC_SPI1_CSN (MTK_PIN_NO(91) | 7)
+
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_MSDC4_DAT6 (MTK_PIN_NO(92) | 1)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_EINT137 (MTK_PIN_NO(92) | 2)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_I2SOUT_DAT (MTK_PIN_NO(92) | 3)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_DAC_DAT_OUT (MTK_PIN_NO(92) | 4)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_PCM1_DO (MTK_PIN_NO(92) | 5)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_A_FUNC_DIN_12 (MTK_PIN_NO(92) | 6)
+#define MT8135_PIN_92_MSDC4_DAT6__FUNC_SPI1_MO (MTK_PIN_NO(92) | 7)
+
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_MSDC4_DAT7 (MTK_PIN_NO(93) | 1)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_EINT138 (MTK_PIN_NO(93) | 2)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_I2SIN_DAT (MTK_PIN_NO(93) | 3)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_PCM1_DI (MTK_PIN_NO(93) | 5)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_A_FUNC_DIN_13 (MTK_PIN_NO(93) | 6)
+#define MT8135_PIN_93_MSDC4_DAT7__FUNC_SPI1_MI (MTK_PIN_NO(93) | 7)
+
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_MSDC4_DAT4 (MTK_PIN_NO(94) | 1)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_EINT135 (MTK_PIN_NO(94) | 2)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_I2SIN_CK (MTK_PIN_NO(94) | 3)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_DAC_CK (MTK_PIN_NO(94) | 4)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_PCM1_CK (MTK_PIN_NO(94) | 5)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_A_FUNC_DIN_14 (MTK_PIN_NO(94) | 6)
+#define MT8135_PIN_94_MSDC4_DAT4__FUNC_SPI1_CLK (MTK_PIN_NO(94) | 7)
+
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_MSDC4_DAT2 (MTK_PIN_NO(95) | 1)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_EINT131 (MTK_PIN_NO(95) | 2)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_I2SIN_WS (MTK_PIN_NO(95) | 3)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_CM2PDN_2X (MTK_PIN_NO(95) | 4)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_DAC_WS (MTK_PIN_NO(95) | 5)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_PCM1_WS (MTK_PIN_NO(95) | 6)
+#define MT8135_PIN_95_MSDC4_DAT2__FUNC_LSCE0B_1X (MTK_PIN_NO(95) | 7)
+
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_MSDC4_CLK (MTK_PIN_NO(96) | 1)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_EINT129 (MTK_PIN_NO(96) | 2)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_DPI1_CK_2X (MTK_PIN_NO(96) | 3)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_CM2PCLK_2X (MTK_PIN_NO(96) | 4)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_PWM4 (MTK_PIN_NO(96) | 5)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_PCM1_DI (MTK_PIN_NO(96) | 6)
+#define MT8135_PIN_96_MSDC4_CLK__FUNC_LSCK_1X (MTK_PIN_NO(96) | 7)
+
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_MSDC4_DAT3 (MTK_PIN_NO(97) | 1)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_EINT132 (MTK_PIN_NO(97) | 2)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_I2SOUT_DAT (MTK_PIN_NO(97) | 3)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_CM2RST_2X (MTK_PIN_NO(97) | 4)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_DAC_DAT_OUT (MTK_PIN_NO(97) | 5)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_PCM1_DO (MTK_PIN_NO(97) | 6)
+#define MT8135_PIN_97_MSDC4_DAT3__FUNC_LSCE1B_1X (MTK_PIN_NO(97) | 7)
+
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_MSDC4_CMD (MTK_PIN_NO(98) | 1)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_EINT128 (MTK_PIN_NO(98) | 2)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_DPI1_DE_2X (MTK_PIN_NO(98) | 3)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_PWM3 (MTK_PIN_NO(98) | 5)
+#define MT8135_PIN_98_MSDC4_CMD__FUNC_LSDA_1X (MTK_PIN_NO(98) | 7)
+
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_MSDC4_RSTB (MTK_PIN_NO(99) | 1)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_EINT130 (MTK_PIN_NO(99) | 2)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_I2SIN_CK (MTK_PIN_NO(99) | 3)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_CM2MCLK_2X (MTK_PIN_NO(99) | 4)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_DAC_CK (MTK_PIN_NO(99) | 5)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_PCM1_CK (MTK_PIN_NO(99) | 6)
+#define MT8135_PIN_99_MSDC4_RSTB__FUNC_LSA0_1X (MTK_PIN_NO(99) | 7)
+
+#define MT8135_PIN_100_SDA0__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define MT8135_PIN_100_SDA0__FUNC_SDA0 (MTK_PIN_NO(100) | 1)
+#define MT8135_PIN_100_SDA0__FUNC_EINT91 (MTK_PIN_NO(100) | 2)
+#define MT8135_PIN_100_SDA0__FUNC_CLKM1 (MTK_PIN_NO(100) | 3)
+#define MT8135_PIN_100_SDA0__FUNC_PWM1 (MTK_PIN_NO(100) | 4)
+#define MT8135_PIN_100_SDA0__FUNC_A_FUNC_DIN_15 (MTK_PIN_NO(100) | 7)
+
+#define MT8135_PIN_101_SCL0__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define MT8135_PIN_101_SCL0__FUNC_SCL0 (MTK_PIN_NO(101) | 1)
+#define MT8135_PIN_101_SCL0__FUNC_EINT90 (MTK_PIN_NO(101) | 2)
+#define MT8135_PIN_101_SCL0__FUNC_CLKM0 (MTK_PIN_NO(101) | 3)
+#define MT8135_PIN_101_SCL0__FUNC_DISP_PWM (MTK_PIN_NO(101) | 4)
+#define MT8135_PIN_101_SCL0__FUNC_A_FUNC_DIN_16 (MTK_PIN_NO(101) | 7)
+
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_EINT10 (MTK_PIN_NO(102) | 1)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_USB_TEST_IO_16 (MTK_PIN_NO(102) | 5)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_TESTB_OUT16 (MTK_PIN_NO(102) | 6)
+#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_A_FUNC_DIN_17 (MTK_PIN_NO(102) | 7)
+
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_EINT11 (MTK_PIN_NO(103) | 1)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_USB_TEST_IO_17 (MTK_PIN_NO(103) | 5)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_TESTB_OUT17 (MTK_PIN_NO(103) | 6)
+#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_A_FUNC_DIN_18 (MTK_PIN_NO(103) | 7)
+
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_EINT16 (MTK_PIN_NO(104) | 1)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_USB_TEST_IO_18 (MTK_PIN_NO(104) | 5)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_TESTB_OUT18 (MTK_PIN_NO(104) | 6)
+#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_A_FUNC_DIN_19 (MTK_PIN_NO(104) | 7)
+
+#define MT8135_PIN_105_I2S_CLK__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT8135_PIN_105_I2S_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(105) | 1)
+#define MT8135_PIN_105_I2S_CLK__FUNC_EINT10 (MTK_PIN_NO(105) | 2)
+#define MT8135_PIN_105_I2S_CLK__FUNC_DAC_CK (MTK_PIN_NO(105) | 3)
+#define MT8135_PIN_105_I2S_CLK__FUNC_PCM1_CK (MTK_PIN_NO(105) | 4)
+#define MT8135_PIN_105_I2S_CLK__FUNC_USB_TEST_IO_19 (MTK_PIN_NO(105) | 5)
+#define MT8135_PIN_105_I2S_CLK__FUNC_TESTB_OUT19 (MTK_PIN_NO(105) | 6)
+#define MT8135_PIN_105_I2S_CLK__FUNC_A_FUNC_DIN_20 (MTK_PIN_NO(105) | 7)
+
+#define MT8135_PIN_106_I2S_WS__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT8135_PIN_106_I2S_WS__FUNC_I2SIN_WS (MTK_PIN_NO(106) | 1)
+#define MT8135_PIN_106_I2S_WS__FUNC_EINT13 (MTK_PIN_NO(106) | 2)
+#define MT8135_PIN_106_I2S_WS__FUNC_DAC_WS (MTK_PIN_NO(106) | 3)
+#define MT8135_PIN_106_I2S_WS__FUNC_PCM1_WS (MTK_PIN_NO(106) | 4)
+#define MT8135_PIN_106_I2S_WS__FUNC_USB_TEST_IO_20 (MTK_PIN_NO(106) | 5)
+#define MT8135_PIN_106_I2S_WS__FUNC_TESTB_OUT20 (MTK_PIN_NO(106) | 6)
+#define MT8135_PIN_106_I2S_WS__FUNC_A_FUNC_DIN_21 (MTK_PIN_NO(106) | 7)
+
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_I2SIN_DAT (MTK_PIN_NO(107) | 1)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_EINT11 (MTK_PIN_NO(107) | 2)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_PCM1_DI (MTK_PIN_NO(107) | 4)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_USB_TEST_IO_21 (MTK_PIN_NO(107) | 5)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_TESTB_OUT22 (MTK_PIN_NO(107) | 6)
+#define MT8135_PIN_107_I2S_DATA_IN__FUNC_A_FUNC_DIN_22 (MTK_PIN_NO(107) | 7)
+
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_I2SOUT_DAT (MTK_PIN_NO(108) | 1)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_EINT12 (MTK_PIN_NO(108) | 2)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(108) | 3)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_PCM1_DO (MTK_PIN_NO(108) | 4)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_USB_TEST_IO_22 (MTK_PIN_NO(108) | 5)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_TESTB_OUT23 (MTK_PIN_NO(108) | 6)
+#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_A_FUNC_DIN_23 (MTK_PIN_NO(108) | 7)
+
+#define MT8135_PIN_109_EINT5__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT8135_PIN_109_EINT5__FUNC_EINT5 (MTK_PIN_NO(109) | 1)
+#define MT8135_PIN_109_EINT5__FUNC_PWM5 (MTK_PIN_NO(109) | 2)
+#define MT8135_PIN_109_EINT5__FUNC_CLKM3 (MTK_PIN_NO(109) | 3)
+#define MT8135_PIN_109_EINT5__FUNC_GPU_JTRSTB (MTK_PIN_NO(109) | 4)
+#define MT8135_PIN_109_EINT5__FUNC_USB_TEST_IO_23 (MTK_PIN_NO(109) | 5)
+#define MT8135_PIN_109_EINT5__FUNC_TESTB_OUT26 (MTK_PIN_NO(109) | 6)
+#define MT8135_PIN_109_EINT5__FUNC_A_FUNC_DIN_24 (MTK_PIN_NO(109) | 7)
+
+#define MT8135_PIN_110_EINT6__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT8135_PIN_110_EINT6__FUNC_EINT6 (MTK_PIN_NO(110) | 1)
+#define MT8135_PIN_110_EINT6__FUNC_PWM6 (MTK_PIN_NO(110) | 2)
+#define MT8135_PIN_110_EINT6__FUNC_CLKM4 (MTK_PIN_NO(110) | 3)
+#define MT8135_PIN_110_EINT6__FUNC_GPU_JTMS (MTK_PIN_NO(110) | 4)
+#define MT8135_PIN_110_EINT6__FUNC_USB_TEST_IO_24 (MTK_PIN_NO(110) | 5)
+#define MT8135_PIN_110_EINT6__FUNC_TESTB_OUT27 (MTK_PIN_NO(110) | 6)
+#define MT8135_PIN_110_EINT6__FUNC_A_FUNC_DIN_25 (MTK_PIN_NO(110) | 7)
+
+#define MT8135_PIN_111_EINT7__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT8135_PIN_111_EINT7__FUNC_EINT7 (MTK_PIN_NO(111) | 1)
+#define MT8135_PIN_111_EINT7__FUNC_PWM7 (MTK_PIN_NO(111) | 2)
+#define MT8135_PIN_111_EINT7__FUNC_CLKM5 (MTK_PIN_NO(111) | 3)
+#define MT8135_PIN_111_EINT7__FUNC_GPU_JTDO (MTK_PIN_NO(111) | 4)
+#define MT8135_PIN_111_EINT7__FUNC_USB_TEST_IO_25 (MTK_PIN_NO(111) | 5)
+#define MT8135_PIN_111_EINT7__FUNC_TESTB_OUT28 (MTK_PIN_NO(111) | 6)
+#define MT8135_PIN_111_EINT7__FUNC_A_FUNC_DIN_26 (MTK_PIN_NO(111) | 7)
+
+#define MT8135_PIN_112_EINT8__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT8135_PIN_112_EINT8__FUNC_EINT8 (MTK_PIN_NO(112) | 1)
+#define MT8135_PIN_112_EINT8__FUNC_DISP_PWM (MTK_PIN_NO(112) | 2)
+#define MT8135_PIN_112_EINT8__FUNC_CLKM6 (MTK_PIN_NO(112) | 3)
+#define MT8135_PIN_112_EINT8__FUNC_GPU_JTDI (MTK_PIN_NO(112) | 4)
+#define MT8135_PIN_112_EINT8__FUNC_USB_TEST_IO_26 (MTK_PIN_NO(112) | 5)
+#define MT8135_PIN_112_EINT8__FUNC_TESTB_OUT29 (MTK_PIN_NO(112) | 6)
+#define MT8135_PIN_112_EINT8__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(112) | 7)
+
+#define MT8135_PIN_113_EINT9__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT8135_PIN_113_EINT9__FUNC_EINT9 (MTK_PIN_NO(113) | 1)
+#define MT8135_PIN_113_EINT9__FUNC_GPU_JTCK (MTK_PIN_NO(113) | 4)
+#define MT8135_PIN_113_EINT9__FUNC_USB_DRVVBUS (MTK_PIN_NO(113) | 5)
+#define MT8135_PIN_113_EINT9__FUNC_TESTB_OUT30 (MTK_PIN_NO(113) | 6)
+#define MT8135_PIN_113_EINT9__FUNC_A_FUNC_DIN_27 (MTK_PIN_NO(113) | 7)
+
+#define MT8135_PIN_114_LPCE1B__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT8135_PIN_114_LPCE1B__FUNC_LPCE1B (MTK_PIN_NO(114) | 1)
+#define MT8135_PIN_114_LPCE1B__FUNC_EINT127 (MTK_PIN_NO(114) | 2)
+#define MT8135_PIN_114_LPCE1B__FUNC_PWM2 (MTK_PIN_NO(114) | 5)
+#define MT8135_PIN_114_LPCE1B__FUNC_TESTB_OUT14 (MTK_PIN_NO(114) | 6)
+#define MT8135_PIN_114_LPCE1B__FUNC_A_FUNC_DIN_28 (MTK_PIN_NO(114) | 7)
+
+#define MT8135_PIN_115_LPCE0B__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT8135_PIN_115_LPCE0B__FUNC_LPCE0B (MTK_PIN_NO(115) | 1)
+#define MT8135_PIN_115_LPCE0B__FUNC_EINT126 (MTK_PIN_NO(115) | 2)
+#define MT8135_PIN_115_LPCE0B__FUNC_PWM1 (MTK_PIN_NO(115) | 5)
+#define MT8135_PIN_115_LPCE0B__FUNC_TESTB_OUT15 (MTK_PIN_NO(115) | 6)
+#define MT8135_PIN_115_LPCE0B__FUNC_A_FUNC_DIN_29 (MTK_PIN_NO(115) | 7)
+
+#define MT8135_PIN_116_DISP_PWM__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT8135_PIN_116_DISP_PWM__FUNC_DISP_PWM (MTK_PIN_NO(116) | 1)
+#define MT8135_PIN_116_DISP_PWM__FUNC_EINT77 (MTK_PIN_NO(116) | 2)
+#define MT8135_PIN_116_DISP_PWM__FUNC_LSDI (MTK_PIN_NO(116) | 3)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM1 (MTK_PIN_NO(116) | 4)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM2 (MTK_PIN_NO(116) | 5)
+#define MT8135_PIN_116_DISP_PWM__FUNC_PWM3 (MTK_PIN_NO(116) | 7)
+
+#define MT8135_PIN_117_EINT1__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT8135_PIN_117_EINT1__FUNC_EINT1 (MTK_PIN_NO(117) | 1)
+#define MT8135_PIN_117_EINT1__FUNC_PWM2 (MTK_PIN_NO(117) | 2)
+#define MT8135_PIN_117_EINT1__FUNC_CLKM1 (MTK_PIN_NO(117) | 3)
+#define MT8135_PIN_117_EINT1__FUNC_USB_TEST_IO_13 (MTK_PIN_NO(117) | 5)
+#define MT8135_PIN_117_EINT1__FUNC_USB_SDA (MTK_PIN_NO(117) | 7)
+
+#define MT8135_PIN_118_EINT2__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT8135_PIN_118_EINT2__FUNC_EINT2 (MTK_PIN_NO(118) | 1)
+#define MT8135_PIN_118_EINT2__FUNC_PWM3 (MTK_PIN_NO(118) | 2)
+#define MT8135_PIN_118_EINT2__FUNC_CLKM2 (MTK_PIN_NO(118) | 3)
+#define MT8135_PIN_118_EINT2__FUNC_USB_TEST_IO_14 (MTK_PIN_NO(118) | 5)
+#define MT8135_PIN_118_EINT2__FUNC_SRCLKENAI2 (MTK_PIN_NO(118) | 6)
+#define MT8135_PIN_118_EINT2__FUNC_A_FUNC_DIN_30 (MTK_PIN_NO(118) | 7)
+
+#define MT8135_PIN_119_EINT3__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT8135_PIN_119_EINT3__FUNC_EINT3 (MTK_PIN_NO(119) | 1)
+#define MT8135_PIN_119_EINT3__FUNC_USB_TEST_IO_15 (MTK_PIN_NO(119) | 5)
+#define MT8135_PIN_119_EINT3__FUNC_SRCLKENAI1 (MTK_PIN_NO(119) | 6)
+#define MT8135_PIN_119_EINT3__FUNC_EXT_26M_CK (MTK_PIN_NO(119) | 7)
+
+#define MT8135_PIN_120_EINT4__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT8135_PIN_120_EINT4__FUNC_EINT4 (MTK_PIN_NO(120) | 1)
+#define MT8135_PIN_120_EINT4__FUNC_PWM4 (MTK_PIN_NO(120) | 2)
+#define MT8135_PIN_120_EINT4__FUNC_USB_DRVVBUS (MTK_PIN_NO(120) | 5)
+#define MT8135_PIN_120_EINT4__FUNC_A_FUNC_DIN_31 (MTK_PIN_NO(120) | 7)
+
+#define MT8135_PIN_121_DPIDE__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT8135_PIN_121_DPIDE__FUNC_DPI0_DE (MTK_PIN_NO(121) | 1)
+#define MT8135_PIN_121_DPIDE__FUNC_EINT100 (MTK_PIN_NO(121) | 2)
+#define MT8135_PIN_121_DPIDE__FUNC_I2SOUT_DAT (MTK_PIN_NO(121) | 3)
+#define MT8135_PIN_121_DPIDE__FUNC_DAC_DAT_OUT (MTK_PIN_NO(121) | 4)
+#define MT8135_PIN_121_DPIDE__FUNC_PCM1_DO (MTK_PIN_NO(121) | 5)
+#define MT8135_PIN_121_DPIDE__FUNC_IRDA_TXD (MTK_PIN_NO(121) | 6)
+
+#define MT8135_PIN_122_DPICK__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT8135_PIN_122_DPICK__FUNC_DPI0_CK (MTK_PIN_NO(122) | 1)
+#define MT8135_PIN_122_DPICK__FUNC_EINT101 (MTK_PIN_NO(122) | 2)
+#define MT8135_PIN_122_DPICK__FUNC_I2SIN_DAT (MTK_PIN_NO(122) | 3)
+#define MT8135_PIN_122_DPICK__FUNC_PCM1_DI (MTK_PIN_NO(122) | 5)
+#define MT8135_PIN_122_DPICK__FUNC_IRDA_PDN (MTK_PIN_NO(122) | 6)
+
+#define MT8135_PIN_123_DPIG4__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT8135_PIN_123_DPIG4__FUNC_DPI0_G4 (MTK_PIN_NO(123) | 1)
+#define MT8135_PIN_123_DPIG4__FUNC_EINT114 (MTK_PIN_NO(123) | 2)
+#define MT8135_PIN_123_DPIG4__FUNC_CM2DAT_2X_0 (MTK_PIN_NO(123) | 4)
+#define MT8135_PIN_123_DPIG4__FUNC_DSP2_ID (MTK_PIN_NO(123) | 5)
+
+#define MT8135_PIN_124_DPIG5__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT8135_PIN_124_DPIG5__FUNC_DPI0_G5 (MTK_PIN_NO(124) | 1)
+#define MT8135_PIN_124_DPIG5__FUNC_EINT115 (MTK_PIN_NO(124) | 2)
+#define MT8135_PIN_124_DPIG5__FUNC_CM2DAT_2X_1 (MTK_PIN_NO(124) | 4)
+#define MT8135_PIN_124_DPIG5__FUNC_DSP2_ICK (MTK_PIN_NO(124) | 5)
+
+#define MT8135_PIN_125_DPIR3__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT8135_PIN_125_DPIR3__FUNC_DPI0_R3 (MTK_PIN_NO(125) | 1)
+#define MT8135_PIN_125_DPIR3__FUNC_EINT121 (MTK_PIN_NO(125) | 2)
+#define MT8135_PIN_125_DPIR3__FUNC_CM2DAT_2X_7 (MTK_PIN_NO(125) | 4)
+
+#define MT8135_PIN_126_DPIG1__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT8135_PIN_126_DPIG1__FUNC_DPI0_G1 (MTK_PIN_NO(126) | 1)
+#define MT8135_PIN_126_DPIG1__FUNC_EINT111 (MTK_PIN_NO(126) | 2)
+#define MT8135_PIN_126_DPIG1__FUNC_DSP1_ICK (MTK_PIN_NO(126) | 5)
+
+#define MT8135_PIN_127_DPIVSYNC__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_DPI0_VSYNC (MTK_PIN_NO(127) | 1)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_EINT98 (MTK_PIN_NO(127) | 2)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_I2SIN_CK (MTK_PIN_NO(127) | 3)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_DAC_CK (MTK_PIN_NO(127) | 4)
+#define MT8135_PIN_127_DPIVSYNC__FUNC_PCM1_CK (MTK_PIN_NO(127) | 5)
+
+#define MT8135_PIN_128_DPIHSYNC__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_DPI0_HSYNC (MTK_PIN_NO(128) | 1)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_EINT99 (MTK_PIN_NO(128) | 2)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_I2SIN_WS (MTK_PIN_NO(128) | 3)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_DAC_WS (MTK_PIN_NO(128) | 4)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_PCM1_WS (MTK_PIN_NO(128) | 5)
+#define MT8135_PIN_128_DPIHSYNC__FUNC_IRDA_RXD (MTK_PIN_NO(128) | 6)
+
+#define MT8135_PIN_129_DPIB0__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define MT8135_PIN_129_DPIB0__FUNC_DPI0_B0 (MTK_PIN_NO(129) | 1)
+#define MT8135_PIN_129_DPIB0__FUNC_EINT102 (MTK_PIN_NO(129) | 2)
+#define MT8135_PIN_129_DPIB0__FUNC_SCL0 (MTK_PIN_NO(129) | 4)
+#define MT8135_PIN_129_DPIB0__FUNC_DISP_PWM (MTK_PIN_NO(129) | 5)
+
+#define MT8135_PIN_130_DPIB1__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define MT8135_PIN_130_DPIB1__FUNC_DPI0_B1 (MTK_PIN_NO(130) | 1)
+#define MT8135_PIN_130_DPIB1__FUNC_EINT103 (MTK_PIN_NO(130) | 2)
+#define MT8135_PIN_130_DPIB1__FUNC_CLKM0 (MTK_PIN_NO(130) | 3)
+#define MT8135_PIN_130_DPIB1__FUNC_SDA0 (MTK_PIN_NO(130) | 4)
+#define MT8135_PIN_130_DPIB1__FUNC_PWM1 (MTK_PIN_NO(130) | 5)
+
+#define MT8135_PIN_131_DPIB2__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define MT8135_PIN_131_DPIB2__FUNC_DPI0_B2 (MTK_PIN_NO(131) | 1)
+#define MT8135_PIN_131_DPIB2__FUNC_EINT104 (MTK_PIN_NO(131) | 2)
+#define MT8135_PIN_131_DPIB2__FUNC_CLKM1 (MTK_PIN_NO(131) | 3)
+#define MT8135_PIN_131_DPIB2__FUNC_SCL1 (MTK_PIN_NO(131) | 4)
+#define MT8135_PIN_131_DPIB2__FUNC_PWM2 (MTK_PIN_NO(131) | 5)
+
+#define MT8135_PIN_132_DPIB3__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define MT8135_PIN_132_DPIB3__FUNC_DPI0_B3 (MTK_PIN_NO(132) | 1)
+#define MT8135_PIN_132_DPIB3__FUNC_EINT105 (MTK_PIN_NO(132) | 2)
+#define MT8135_PIN_132_DPIB3__FUNC_CLKM2 (MTK_PIN_NO(132) | 3)
+#define MT8135_PIN_132_DPIB3__FUNC_SDA1 (MTK_PIN_NO(132) | 4)
+#define MT8135_PIN_132_DPIB3__FUNC_PWM3 (MTK_PIN_NO(132) | 5)
+
+#define MT8135_PIN_133_DPIB4__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define MT8135_PIN_133_DPIB4__FUNC_DPI0_B4 (MTK_PIN_NO(133) | 1)
+#define MT8135_PIN_133_DPIB4__FUNC_EINT106 (MTK_PIN_NO(133) | 2)
+#define MT8135_PIN_133_DPIB4__FUNC_CLKM3 (MTK_PIN_NO(133) | 3)
+#define MT8135_PIN_133_DPIB4__FUNC_SCL2 (MTK_PIN_NO(133) | 4)
+#define MT8135_PIN_133_DPIB4__FUNC_PWM4 (MTK_PIN_NO(133) | 5)
+
+#define MT8135_PIN_134_DPIB5__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define MT8135_PIN_134_DPIB5__FUNC_DPI0_B5 (MTK_PIN_NO(134) | 1)
+#define MT8135_PIN_134_DPIB5__FUNC_EINT107 (MTK_PIN_NO(134) | 2)
+#define MT8135_PIN_134_DPIB5__FUNC_CLKM4 (MTK_PIN_NO(134) | 3)
+#define MT8135_PIN_134_DPIB5__FUNC_SDA2 (MTK_PIN_NO(134) | 4)
+#define MT8135_PIN_134_DPIB5__FUNC_PWM5 (MTK_PIN_NO(134) | 5)
+
+#define MT8135_PIN_135_DPIB6__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
+#define MT8135_PIN_135_DPIB6__FUNC_DPI0_B6 (MTK_PIN_NO(135) | 1)
+#define MT8135_PIN_135_DPIB6__FUNC_EINT108 (MTK_PIN_NO(135) | 2)
+#define MT8135_PIN_135_DPIB6__FUNC_CLKM5 (MTK_PIN_NO(135) | 3)
+#define MT8135_PIN_135_DPIB6__FUNC_SCL3 (MTK_PIN_NO(135) | 4)
+#define MT8135_PIN_135_DPIB6__FUNC_PWM6 (MTK_PIN_NO(135) | 5)
+
+#define MT8135_PIN_136_DPIB7__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
+#define MT8135_PIN_136_DPIB7__FUNC_DPI0_B7 (MTK_PIN_NO(136) | 1)
+#define MT8135_PIN_136_DPIB7__FUNC_EINT109 (MTK_PIN_NO(136) | 2)
+#define MT8135_PIN_136_DPIB7__FUNC_CLKM6 (MTK_PIN_NO(136) | 3)
+#define MT8135_PIN_136_DPIB7__FUNC_SDA3 (MTK_PIN_NO(136) | 4)
+#define MT8135_PIN_136_DPIB7__FUNC_PWM7 (MTK_PIN_NO(136) | 5)
+
+#define MT8135_PIN_137_DPIG0__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
+#define MT8135_PIN_137_DPIG0__FUNC_DPI0_G0 (MTK_PIN_NO(137) | 1)
+#define MT8135_PIN_137_DPIG0__FUNC_EINT110 (MTK_PIN_NO(137) | 2)
+#define MT8135_PIN_137_DPIG0__FUNC_DSP1_ID (MTK_PIN_NO(137) | 5)
+
+#define MT8135_PIN_138_DPIG2__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
+#define MT8135_PIN_138_DPIG2__FUNC_DPI0_G2 (MTK_PIN_NO(138) | 1)
+#define MT8135_PIN_138_DPIG2__FUNC_EINT112 (MTK_PIN_NO(138) | 2)
+#define MT8135_PIN_138_DPIG2__FUNC_DSP1_IMS (MTK_PIN_NO(138) | 5)
+
+#define MT8135_PIN_139_DPIG3__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
+#define MT8135_PIN_139_DPIG3__FUNC_DPI0_G3 (MTK_PIN_NO(139) | 1)
+#define MT8135_PIN_139_DPIG3__FUNC_EINT113 (MTK_PIN_NO(139) | 2)
+#define MT8135_PIN_139_DPIG3__FUNC_DSP2_IMS (MTK_PIN_NO(139) | 5)
+
+#define MT8135_PIN_140_DPIG6__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
+#define MT8135_PIN_140_DPIG6__FUNC_DPI0_G6 (MTK_PIN_NO(140) | 1)
+#define MT8135_PIN_140_DPIG6__FUNC_EINT116 (MTK_PIN_NO(140) | 2)
+#define MT8135_PIN_140_DPIG6__FUNC_CM2DAT_2X_2 (MTK_PIN_NO(140) | 4)
+
+#define MT8135_PIN_141_DPIG7__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
+#define MT8135_PIN_141_DPIG7__FUNC_DPI0_G7 (MTK_PIN_NO(141) | 1)
+#define MT8135_PIN_141_DPIG7__FUNC_EINT117 (MTK_PIN_NO(141) | 2)
+#define MT8135_PIN_141_DPIG7__FUNC_CM2DAT_2X_3 (MTK_PIN_NO(141) | 4)
+
+#define MT8135_PIN_142_DPIR0__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
+#define MT8135_PIN_142_DPIR0__FUNC_DPI0_R0 (MTK_PIN_NO(142) | 1)
+#define MT8135_PIN_142_DPIR0__FUNC_EINT118 (MTK_PIN_NO(142) | 2)
+#define MT8135_PIN_142_DPIR0__FUNC_CM2DAT_2X_4 (MTK_PIN_NO(142) | 4)
+
+#define MT8135_PIN_143_DPIR1__FUNC_GPIO143 (MTK_PIN_NO(143) | 0)
+#define MT8135_PIN_143_DPIR1__FUNC_DPI0_R1 (MTK_PIN_NO(143) | 1)
+#define MT8135_PIN_143_DPIR1__FUNC_EINT119 (MTK_PIN_NO(143) | 2)
+#define MT8135_PIN_143_DPIR1__FUNC_CM2DAT_2X_5 (MTK_PIN_NO(143) | 4)
+
+#define MT8135_PIN_144_DPIR2__FUNC_GPIO144 (MTK_PIN_NO(144) | 0)
+#define MT8135_PIN_144_DPIR2__FUNC_DPI0_R2 (MTK_PIN_NO(144) | 1)
+#define MT8135_PIN_144_DPIR2__FUNC_EINT120 (MTK_PIN_NO(144) | 2)
+#define MT8135_PIN_144_DPIR2__FUNC_CM2DAT_2X_6 (MTK_PIN_NO(144) | 4)
+
+#define MT8135_PIN_145_DPIR4__FUNC_GPIO145 (MTK_PIN_NO(145) | 0)
+#define MT8135_PIN_145_DPIR4__FUNC_DPI0_R4 (MTK_PIN_NO(145) | 1)
+#define MT8135_PIN_145_DPIR4__FUNC_EINT122 (MTK_PIN_NO(145) | 2)
+#define MT8135_PIN_145_DPIR4__FUNC_CM2DAT_2X_8 (MTK_PIN_NO(145) | 4)
+
+#define MT8135_PIN_146_DPIR5__FUNC_GPIO146 (MTK_PIN_NO(146) | 0)
+#define MT8135_PIN_146_DPIR5__FUNC_DPI0_R5 (MTK_PIN_NO(146) | 1)
+#define MT8135_PIN_146_DPIR5__FUNC_EINT123 (MTK_PIN_NO(146) | 2)
+#define MT8135_PIN_146_DPIR5__FUNC_CM2DAT_2X_9 (MTK_PIN_NO(146) | 4)
+
+#define MT8135_PIN_147_DPIR6__FUNC_GPIO147 (MTK_PIN_NO(147) | 0)
+#define MT8135_PIN_147_DPIR6__FUNC_DPI0_R6 (MTK_PIN_NO(147) | 1)
+#define MT8135_PIN_147_DPIR6__FUNC_EINT124 (MTK_PIN_NO(147) | 2)
+#define MT8135_PIN_147_DPIR6__FUNC_CM2VSYNC_2X (MTK_PIN_NO(147) | 4)
+
+#define MT8135_PIN_148_DPIR7__FUNC_GPIO148 (MTK_PIN_NO(148) | 0)
+#define MT8135_PIN_148_DPIR7__FUNC_DPI0_R7 (MTK_PIN_NO(148) | 1)
+#define MT8135_PIN_148_DPIR7__FUNC_EINT125 (MTK_PIN_NO(148) | 2)
+#define MT8135_PIN_148_DPIR7__FUNC_CM2HSYNC_2X (MTK_PIN_NO(148) | 4)
+
+#define MT8135_PIN_149_TDN3__FUNC_GPIO149 (MTK_PIN_NO(149) | 0)
+#define MT8135_PIN_149_TDN3__FUNC_EINT36 (MTK_PIN_NO(149) | 2)
+
+#define MT8135_PIN_150_TDP3__FUNC_GPIO150 (MTK_PIN_NO(150) | 0)
+#define MT8135_PIN_150_TDP3__FUNC_EINT35 (MTK_PIN_NO(150) | 2)
+
+#define MT8135_PIN_151_TDN2__FUNC_GPIO151 (MTK_PIN_NO(151) | 0)
+#define MT8135_PIN_151_TDN2__FUNC_EINT169 (MTK_PIN_NO(151) | 2)
+
+#define MT8135_PIN_152_TDP2__FUNC_GPIO152 (MTK_PIN_NO(152) | 0)
+#define MT8135_PIN_152_TDP2__FUNC_EINT168 (MTK_PIN_NO(152) | 2)
+
+#define MT8135_PIN_153_TCN__FUNC_GPIO153 (MTK_PIN_NO(153) | 0)
+#define MT8135_PIN_153_TCN__FUNC_EINT163 (MTK_PIN_NO(153) | 2)
+
+#define MT8135_PIN_154_TCP__FUNC_GPIO154 (MTK_PIN_NO(154) | 0)
+#define MT8135_PIN_154_TCP__FUNC_EINT162 (MTK_PIN_NO(154) | 2)
+
+#define MT8135_PIN_155_TDN1__FUNC_GPIO155 (MTK_PIN_NO(155) | 0)
+#define MT8135_PIN_155_TDN1__FUNC_EINT167 (MTK_PIN_NO(155) | 2)
+
+#define MT8135_PIN_156_TDP1__FUNC_GPIO156 (MTK_PIN_NO(156) | 0)
+#define MT8135_PIN_156_TDP1__FUNC_EINT166 (MTK_PIN_NO(156) | 2)
+
+#define MT8135_PIN_157_TDN0__FUNC_GPIO157 (MTK_PIN_NO(157) | 0)
+#define MT8135_PIN_157_TDN0__FUNC_EINT165 (MTK_PIN_NO(157) | 2)
+
+#define MT8135_PIN_158_TDP0__FUNC_GPIO158 (MTK_PIN_NO(158) | 0)
+#define MT8135_PIN_158_TDP0__FUNC_EINT164 (MTK_PIN_NO(158) | 2)
+
+#define MT8135_PIN_159_RDN3__FUNC_GPIO159 (MTK_PIN_NO(159) | 0)
+#define MT8135_PIN_159_RDN3__FUNC_EINT18 (MTK_PIN_NO(159) | 2)
+
+#define MT8135_PIN_160_RDP3__FUNC_GPIO160 (MTK_PIN_NO(160) | 0)
+#define MT8135_PIN_160_RDP3__FUNC_EINT30 (MTK_PIN_NO(160) | 2)
+
+#define MT8135_PIN_161_RDN2__FUNC_GPIO161 (MTK_PIN_NO(161) | 0)
+#define MT8135_PIN_161_RDN2__FUNC_EINT31 (MTK_PIN_NO(161) | 2)
+
+#define MT8135_PIN_162_RDP2__FUNC_GPIO162 (MTK_PIN_NO(162) | 0)
+#define MT8135_PIN_162_RDP2__FUNC_EINT32 (MTK_PIN_NO(162) | 2)
+
+#define MT8135_PIN_163_RCN__FUNC_GPIO163 (MTK_PIN_NO(163) | 0)
+#define MT8135_PIN_163_RCN__FUNC_EINT33 (MTK_PIN_NO(163) | 2)
+
+#define MT8135_PIN_164_RCP__FUNC_GPIO164 (MTK_PIN_NO(164) | 0)
+#define MT8135_PIN_164_RCP__FUNC_EINT39 (MTK_PIN_NO(164) | 2)
+
+#define MT8135_PIN_165_RDN1__FUNC_GPIO165 (MTK_PIN_NO(165) | 0)
+
+#define MT8135_PIN_166_RDP1__FUNC_GPIO166 (MTK_PIN_NO(166) | 0)
+
+#define MT8135_PIN_167_RDN0__FUNC_GPIO167 (MTK_PIN_NO(167) | 0)
+
+#define MT8135_PIN_168_RDP0__FUNC_GPIO168 (MTK_PIN_NO(168) | 0)
+
+#define MT8135_PIN_169_RDN1_A__FUNC_GPIO169 (MTK_PIN_NO(169) | 0)
+#define MT8135_PIN_169_RDN1_A__FUNC_CMDAT6 (MTK_PIN_NO(169) | 1)
+#define MT8135_PIN_169_RDN1_A__FUNC_EINT175 (MTK_PIN_NO(169) | 2)
+
+#define MT8135_PIN_170_RDP1_A__FUNC_GPIO170 (MTK_PIN_NO(170) | 0)
+#define MT8135_PIN_170_RDP1_A__FUNC_CMDAT7 (MTK_PIN_NO(170) | 1)
+#define MT8135_PIN_170_RDP1_A__FUNC_EINT174 (MTK_PIN_NO(170) | 2)
+
+#define MT8135_PIN_171_RCN_A__FUNC_GPIO171 (MTK_PIN_NO(171) | 0)
+#define MT8135_PIN_171_RCN_A__FUNC_CMDAT8 (MTK_PIN_NO(171) | 1)
+#define MT8135_PIN_171_RCN_A__FUNC_EINT171 (MTK_PIN_NO(171) | 2)
+
+#define MT8135_PIN_172_RCP_A__FUNC_GPIO172 (MTK_PIN_NO(172) | 0)
+#define MT8135_PIN_172_RCP_A__FUNC_CMDAT9 (MTK_PIN_NO(172) | 1)
+#define MT8135_PIN_172_RCP_A__FUNC_EINT170 (MTK_PIN_NO(172) | 2)
+
+#define MT8135_PIN_173_RDN0_A__FUNC_GPIO173 (MTK_PIN_NO(173) | 0)
+#define MT8135_PIN_173_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(173) | 1)
+#define MT8135_PIN_173_RDN0_A__FUNC_EINT173 (MTK_PIN_NO(173) | 2)
+
+#define MT8135_PIN_174_RDP0_A__FUNC_GPIO174 (MTK_PIN_NO(174) | 0)
+#define MT8135_PIN_174_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(174) | 1)
+#define MT8135_PIN_174_RDP0_A__FUNC_EINT172 (MTK_PIN_NO(174) | 2)
+
+#define MT8135_PIN_175_RDN1_B__FUNC_GPIO175 (MTK_PIN_NO(175) | 0)
+#define MT8135_PIN_175_RDN1_B__FUNC_CMDAT2 (MTK_PIN_NO(175) | 1)
+#define MT8135_PIN_175_RDN1_B__FUNC_EINT181 (MTK_PIN_NO(175) | 2)
+#define MT8135_PIN_175_RDN1_B__FUNC_CMCSD2 (MTK_PIN_NO(175) | 3)
+
+#define MT8135_PIN_176_RDP1_B__FUNC_GPIO176 (MTK_PIN_NO(176) | 0)
+#define MT8135_PIN_176_RDP1_B__FUNC_CMDAT3 (MTK_PIN_NO(176) | 1)
+#define MT8135_PIN_176_RDP1_B__FUNC_EINT180 (MTK_PIN_NO(176) | 2)
+#define MT8135_PIN_176_RDP1_B__FUNC_CMCSD3 (MTK_PIN_NO(176) | 3)
+
+#define MT8135_PIN_177_RCN_B__FUNC_GPIO177 (MTK_PIN_NO(177) | 0)
+#define MT8135_PIN_177_RCN_B__FUNC_CMDAT4 (MTK_PIN_NO(177) | 1)
+#define MT8135_PIN_177_RCN_B__FUNC_EINT177 (MTK_PIN_NO(177) | 2)
+
+#define MT8135_PIN_178_RCP_B__FUNC_GPIO178 (MTK_PIN_NO(178) | 0)
+#define MT8135_PIN_178_RCP_B__FUNC_CMDAT5 (MTK_PIN_NO(178) | 1)
+#define MT8135_PIN_178_RCP_B__FUNC_EINT176 (MTK_PIN_NO(178) | 2)
+
+#define MT8135_PIN_179_RDN0_B__FUNC_GPIO179 (MTK_PIN_NO(179) | 0)
+#define MT8135_PIN_179_RDN0_B__FUNC_CMDAT0 (MTK_PIN_NO(179) | 1)
+#define MT8135_PIN_179_RDN0_B__FUNC_EINT179 (MTK_PIN_NO(179) | 2)
+#define MT8135_PIN_179_RDN0_B__FUNC_CMCSD0 (MTK_PIN_NO(179) | 3)
+
+#define MT8135_PIN_180_RDP0_B__FUNC_GPIO180 (MTK_PIN_NO(180) | 0)
+#define MT8135_PIN_180_RDP0_B__FUNC_CMDAT1 (MTK_PIN_NO(180) | 1)
+#define MT8135_PIN_180_RDP0_B__FUNC_EINT178 (MTK_PIN_NO(180) | 2)
+#define MT8135_PIN_180_RDP0_B__FUNC_CMCSD1 (MTK_PIN_NO(180) | 3)
+
+#define MT8135_PIN_181_CMPCLK__FUNC_GPIO181 (MTK_PIN_NO(181) | 0)
+#define MT8135_PIN_181_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(181) | 1)
+#define MT8135_PIN_181_CMPCLK__FUNC_EINT182 (MTK_PIN_NO(181) | 2)
+#define MT8135_PIN_181_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(181) | 3)
+#define MT8135_PIN_181_CMPCLK__FUNC_CM2MCLK_4X (MTK_PIN_NO(181) | 4)
+#define MT8135_PIN_181_CMPCLK__FUNC_TS_AUXADC_SEL_3 (MTK_PIN_NO(181) | 5)
+#define MT8135_PIN_181_CMPCLK__FUNC_VENC_TEST_CK (MTK_PIN_NO(181) | 6)
+#define MT8135_PIN_181_CMPCLK__FUNC_TESTA_OUT27 (MTK_PIN_NO(181) | 7)
+
+#define MT8135_PIN_182_CMMCLK__FUNC_GPIO182 (MTK_PIN_NO(182) | 0)
+#define MT8135_PIN_182_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(182) | 1)
+#define MT8135_PIN_182_CMMCLK__FUNC_EINT183 (MTK_PIN_NO(182) | 2)
+#define MT8135_PIN_182_CMMCLK__FUNC_TS_AUXADC_SEL_2 (MTK_PIN_NO(182) | 5)
+#define MT8135_PIN_182_CMMCLK__FUNC_TESTA_OUT28 (MTK_PIN_NO(182) | 7)
+
+#define MT8135_PIN_183_CMRST__FUNC_GPIO183 (MTK_PIN_NO(183) | 0)
+#define MT8135_PIN_183_CMRST__FUNC_CMRST (MTK_PIN_NO(183) | 1)
+#define MT8135_PIN_183_CMRST__FUNC_EINT185 (MTK_PIN_NO(183) | 2)
+#define MT8135_PIN_183_CMRST__FUNC_TS_AUXADC_SEL_1 (MTK_PIN_NO(183) | 5)
+#define MT8135_PIN_183_CMRST__FUNC_TESTA_OUT30 (MTK_PIN_NO(183) | 7)
+
+#define MT8135_PIN_184_CMPDN__FUNC_GPIO184 (MTK_PIN_NO(184) | 0)
+#define MT8135_PIN_184_CMPDN__FUNC_CMPDN (MTK_PIN_NO(184) | 1)
+#define MT8135_PIN_184_CMPDN__FUNC_EINT184 (MTK_PIN_NO(184) | 2)
+#define MT8135_PIN_184_CMPDN__FUNC_TS_AUXADC_SEL_0 (MTK_PIN_NO(184) | 5)
+#define MT8135_PIN_184_CMPDN__FUNC_TESTA_OUT29 (MTK_PIN_NO(184) | 7)
+
+#define MT8135_PIN_185_CMFLASH__FUNC_GPIO185 (MTK_PIN_NO(185) | 0)
+#define MT8135_PIN_185_CMFLASH__FUNC_CMFLASH (MTK_PIN_NO(185) | 1)
+#define MT8135_PIN_185_CMFLASH__FUNC_EINT186 (MTK_PIN_NO(185) | 2)
+#define MT8135_PIN_185_CMFLASH__FUNC_CM2MCLK_3X (MTK_PIN_NO(185) | 3)
+#define MT8135_PIN_185_CMFLASH__FUNC_MFG_TEST_CK_1 (MTK_PIN_NO(185) | 6)
+#define MT8135_PIN_185_CMFLASH__FUNC_TESTA_OUT31 (MTK_PIN_NO(185) | 7)
+
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_GPIO186 (MTK_PIN_NO(186) | 0)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_MRG_I2S_P_CLK (MTK_PIN_NO(186) | 1)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_EINT14 (MTK_PIN_NO(186) | 2)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(186) | 3)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_PCM0_CK (MTK_PIN_NO(186) | 4)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_DSP2_ICK (MTK_PIN_NO(186) | 5)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_IMG_TEST_CK (MTK_PIN_NO(186) | 6)
+#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_USB_SCL (MTK_PIN_NO(186) | 7)
+
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_GPIO187 (MTK_PIN_NO(187) | 0)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_MRG_I2S_SYNC (MTK_PIN_NO(187) | 1)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_EINT16 (MTK_PIN_NO(187) | 2)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_I2SIN_WS (MTK_PIN_NO(187) | 3)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_PCM0_WS (MTK_PIN_NO(187) | 4)
+#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_DISP_TEST_CK (MTK_PIN_NO(187) | 6)
+
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_GPIO188 (MTK_PIN_NO(188) | 0)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MRG_I2S_PCM_RX (MTK_PIN_NO(188) | 1)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_EINT15 (MTK_PIN_NO(188) | 2)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_I2SIN_DAT (MTK_PIN_NO(188) | 3)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_PCM0_DI (MTK_PIN_NO(188) | 4)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_DSP2_ID (MTK_PIN_NO(188) | 5)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MFG_TEST_CK (MTK_PIN_NO(188) | 6)
+#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_USB_SDA (MTK_PIN_NO(188) | 7)
+
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_GPIO189 (MTK_PIN_NO(189) | 0)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_MRG_I2S_PCM_TX (MTK_PIN_NO(189) | 1)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_EINT17 (MTK_PIN_NO(189) | 2)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_I2SOUT_DAT (MTK_PIN_NO(189) | 3)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_PCM0_DO (MTK_PIN_NO(189) | 4)
+#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_VDEC_TEST_CK (MTK_PIN_NO(189) | 6)
+
+#define MT8135_PIN_190_SRCLKENAI__FUNC_GPIO190 (MTK_PIN_NO(190) | 0)
+#define MT8135_PIN_190_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(190) | 1)
+
+#define MT8135_PIN_191_URXD3__FUNC_GPIO191 (MTK_PIN_NO(191) | 0)
+#define MT8135_PIN_191_URXD3__FUNC_URXD3 (MTK_PIN_NO(191) | 1)
+#define MT8135_PIN_191_URXD3__FUNC_EINT87 (MTK_PIN_NO(191) | 2)
+#define MT8135_PIN_191_URXD3__FUNC_UTXD3 (MTK_PIN_NO(191) | 3)
+#define MT8135_PIN_191_URXD3__FUNC_TS_AUX_ST (MTK_PIN_NO(191) | 5)
+#define MT8135_PIN_191_URXD3__FUNC_PWM4 (MTK_PIN_NO(191) | 6)
+
+#define MT8135_PIN_192_UTXD3__FUNC_GPIO192 (MTK_PIN_NO(192) | 0)
+#define MT8135_PIN_192_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(192) | 1)
+#define MT8135_PIN_192_UTXD3__FUNC_EINT86 (MTK_PIN_NO(192) | 2)
+#define MT8135_PIN_192_UTXD3__FUNC_URXD3 (MTK_PIN_NO(192) | 3)
+#define MT8135_PIN_192_UTXD3__FUNC_TS_AUX_CS_B (MTK_PIN_NO(192) | 5)
+#define MT8135_PIN_192_UTXD3__FUNC_PWM3 (MTK_PIN_NO(192) | 6)
+
+#define MT8135_PIN_193_SDA2__FUNC_GPIO193 (MTK_PIN_NO(193) | 0)
+#define MT8135_PIN_193_SDA2__FUNC_SDA2 (MTK_PIN_NO(193) | 1)
+#define MT8135_PIN_193_SDA2__FUNC_EINT95 (MTK_PIN_NO(193) | 2)
+#define MT8135_PIN_193_SDA2__FUNC_CLKM5 (MTK_PIN_NO(193) | 3)
+#define MT8135_PIN_193_SDA2__FUNC_PWM5 (MTK_PIN_NO(193) | 4)
+#define MT8135_PIN_193_SDA2__FUNC_TS_AUX_PWDB (MTK_PIN_NO(193) | 5)
+
+#define MT8135_PIN_194_SCL2__FUNC_GPIO194 (MTK_PIN_NO(194) | 0)
+#define MT8135_PIN_194_SCL2__FUNC_SCL2 (MTK_PIN_NO(194) | 1)
+#define MT8135_PIN_194_SCL2__FUNC_EINT94 (MTK_PIN_NO(194) | 2)
+#define MT8135_PIN_194_SCL2__FUNC_CLKM4 (MTK_PIN_NO(194) | 3)
+#define MT8135_PIN_194_SCL2__FUNC_PWM4 (MTK_PIN_NO(194) | 4)
+#define MT8135_PIN_194_SCL2__FUNC_TS_AUXADC_TEST_CK (MTK_PIN_NO(194) | 5)
+
+#define MT8135_PIN_195_SDA1__FUNC_GPIO195 (MTK_PIN_NO(195) | 0)
+#define MT8135_PIN_195_SDA1__FUNC_SDA1 (MTK_PIN_NO(195) | 1)
+#define MT8135_PIN_195_SDA1__FUNC_EINT93 (MTK_PIN_NO(195) | 2)
+#define MT8135_PIN_195_SDA1__FUNC_CLKM3 (MTK_PIN_NO(195) | 3)
+#define MT8135_PIN_195_SDA1__FUNC_PWM3 (MTK_PIN_NO(195) | 4)
+#define MT8135_PIN_195_SDA1__FUNC_TS_AUX_SCLK_PWDB (MTK_PIN_NO(195) | 5)
+
+#define MT8135_PIN_196_SCL1__FUNC_GPIO196 (MTK_PIN_NO(196) | 0)
+#define MT8135_PIN_196_SCL1__FUNC_SCL1 (MTK_PIN_NO(196) | 1)
+#define MT8135_PIN_196_SCL1__FUNC_EINT92 (MTK_PIN_NO(196) | 2)
+#define MT8135_PIN_196_SCL1__FUNC_CLKM2 (MTK_PIN_NO(196) | 3)
+#define MT8135_PIN_196_SCL1__FUNC_PWM2 (MTK_PIN_NO(196) | 4)
+#define MT8135_PIN_196_SCL1__FUNC_TS_AUX_DIN (MTK_PIN_NO(196) | 5)
+
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_GPIO197 (MTK_PIN_NO(197) | 0)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(197) | 1)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_EINT71 (MTK_PIN_NO(197) | 2)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_SCL6 (MTK_PIN_NO(197) | 3)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_PWM5 (MTK_PIN_NO(197) | 4)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_CLKM4 (MTK_PIN_NO(197) | 5)
+#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MFG_TEST_CK_2 (MTK_PIN_NO(197) | 6)
+
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_GPIO198 (MTK_PIN_NO(198) | 0)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(198) | 1)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_EINT72 (MTK_PIN_NO(198) | 2)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_SDA6 (MTK_PIN_NO(198) | 3)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_PWM6 (MTK_PIN_NO(198) | 4)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_CLKM5 (MTK_PIN_NO(198) | 5)
+#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MFG_TEST_CK_3 (MTK_PIN_NO(198) | 6)
+
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(199) | 1)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_EINT68 (MTK_PIN_NO(199) | 2)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_SDA2 (MTK_PIN_NO(199) | 3)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_PWM2 (MTK_PIN_NO(199) | 4)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_CLKM1 (MTK_PIN_NO(199) | 5)
+#define MT8135_PIN_199_MSDC3_CMD__FUNC_MFG_TEST_CK_4 (MTK_PIN_NO(199) | 6)
+
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(200) | 1)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_EINT67 (MTK_PIN_NO(200) | 2)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_SCL2 (MTK_PIN_NO(200) | 3)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_PWM1 (MTK_PIN_NO(200) | 4)
+#define MT8135_PIN_200_MSDC3_CLK__FUNC_CLKM0 (MTK_PIN_NO(200) | 5)
+
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(201) | 1)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_EINT70 (MTK_PIN_NO(201) | 2)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_SDA3 (MTK_PIN_NO(201) | 3)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_PWM4 (MTK_PIN_NO(201) | 4)
+#define MT8135_PIN_201_MSDC3_DAT1__FUNC_CLKM3 (MTK_PIN_NO(201) | 5)
+
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_GPIO202 (MTK_PIN_NO(202) | 0)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(202) | 1)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_EINT69 (MTK_PIN_NO(202) | 2)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_SCL3 (MTK_PIN_NO(202) | 3)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_PWM3 (MTK_PIN_NO(202) | 4)
+#define MT8135_PIN_202_MSDC3_DAT0__FUNC_CLKM2 (MTK_PIN_NO(202) | 5)
+
+#endif /* __DTS_MT8135_PINFUNC_H */
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index a161e99..0aba9eb 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -15,6 +15,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "skeleton64.dtsi"
+#include "mt8135-pinfunc.h"
 
 / {
 	compatible = "mediatek,mt8135";
@@ -101,6 +102,29 @@
 		compatible = "simple-bus";
 		ranges;
 
+		/*
+		 * Pinctrl access register at 0x10005000 and 0x1020c000 through
+		 * regmap. Register 0x1000b000 is used by EINT.
+		 */
+		pio: pinctrl at 10005000 {
+			compatible = "mediatek,mt8135-pinctrl";
+			reg = <0 0x1000b000 0 0x1000>;
+			mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
+			pins-are-numbered;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
+			compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
+			reg = <0 0x10005000 0 0x1000>;
+		};
+
 		timer: timer at 10008000 {
 			compatible = "mediatek,mt8135-timer",
 					"mediatek,mt6577-timer";
@@ -119,6 +143,11 @@
 			reg = <0 0x10200030 0 0x1c>;
 		};
 
+		syscfg_pctl_b: syscfg_pctl_b at 1020c000 {
+			compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
+			reg = <0 0x1020c000 0 0x1000>;
+		};
+
 		gic: interrupt-controller at 10211000 {
 			compatible = "arm,cortex-a15-gic";
 			interrupt-controller;
-- 
1.8.1.1.dirty



From yingjoe.chen at mediatek.com  Thu Apr 30 23:49:31 2015
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Fri, 1 May 2015 14:49:31 +0800
Subject: [PATCH v2 2/2] arm64: dts: mt8173: Fixup pinctrl nodes
In-Reply-To: <1430462971-28195-1-git-send-email-yingjoe.chen@mediatek.com>
References: <1430462971-28195-1-git-send-email-yingjoe.chen@mediatek.com>
Message-ID: <1430462971-28195-2-git-send-email-yingjoe.chen@mediatek.com>

The 8173 pinctrl node doesn't follow dts convention. Fix them.
Also add a comment to explain pinctrl register usage to make it
more clear.

Signed-off-by: Yingjoe Chen <yingjoe.chen at mediatek.com>
Reviewed-by: Daniel Kurtz <djkurtz at chromium.org>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 924fdb6..4595196 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -106,14 +106,13 @@
 		compatible = "simple-bus";
 		ranges;
 
-		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
-			compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon";
-			reg = <0 0x10005000 0 0x1000>;
-		};
-
-		pio: pinctrl at 0x10005000 {
+		/*
+		 * Pinctrl access register at 0x10005000 through regmap.
+		 * Register 0x1000b000 is used by EINT.
+		 */
+		pio: pinctrl at 10005000 {
 			compatible = "mediatek,mt8173-pinctrl";
-			reg = <0 0x1000B000 0 0x1000>;
+			reg = <0 0x1000b000 0 0x1000>;
 			mediatek,pctl-regmap = <&syscfg_pctl_a>;
 			pins-are-numbered;
 			gpio-controller;
@@ -121,8 +120,13 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
-						<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
-						<GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+				     <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		syscfg_pctl_a: syscfg_pctl_a at 10005000 {
+			compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon";
+			reg = <0 0x10005000 0 0x1000>;
 		};
 
 		sysirq: intpol-controller at 10200620 {
-- 
1.8.1.1.dirty



