[ALPS04079775] Platform: Kernel-4.14 Migration

[Detail] Code merged from yocto

MTK-Commit-Id: 4d1482911601922594964945fb3b831a66b762ae

Change-Id: I89df40172a12826b990d4899a227edae1ee9647e
CR-Id: ALPS04079775
Feature: [Module]Kernel Maintenance
Signed-off-by: season chen <season.chen@mediatek.com>
(cherry-pick from 1a3ac023e6ba213a6f43e5ec432763b77579ee63)
This commit is contained in:
season chen
2020-03-03 00:22:54 +08:00
committed by MY Chuang
parent 6b11883136
commit 5e0579f23f
38 changed files with 3918 additions and 186 deletions

View File

@@ -36,24 +36,33 @@ each local arbiter.
like display, video decode, and camera. And there are different ports
in each larb. Take a example, There are many ports like MC, PP, VLD in the
video decode local arbiter, all these ports are according to the video HW.
In some Socs, there may be a GALS(Global Async Local Sync) module between
smi-common and m4u, and additional GALS module between smi-larb and
smi-common. GALS can been seen as a "asynchronous fifo" which could help
synchronize for the modules in different clock frequence.
Required properties:
- compatible : must be one of the following string:
"mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
"mediatek,mt2712-m4u" for mt2712 which uses generation two m4u HW.
"mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
"mediatek,mt8183-m4u" for mt8183 which uses generation two m4u HW.
- reg : m4u register base and size.
- interrupts : the interrupt of m4u.
- clocks : must contain one entry for each clock-names.
- clock-names : must be "bclk", It is the block clock of m4u.
- clock-names : Only 1 optional clock:
- "bclk": the block clock of m4u.
Note that m4u use EMI clock which always has been enabled before kernel if
there is no this "bclk", like mt8183.
- mediatek,larbs : List of phandle to the local arbiters in the current Socs.
Refer to bindings/memory-controllers/mediatek,smi-larb.txt. It must sort
according to the local arbiter index, like larb0, larb1, larb2...
- iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
Specifies the mtk_m4u_id as defined in
dt-binding/memory/mt2701-larb-port.h for mt2701,
dt-binding/memory/mt2712-larb-port.h for mt2712, and
dt-binding/memory/mt8173-larb-port.h for mt8173.
dt-binding/memory/mt2712-larb-port.h for mt2712,
dt-binding/memory/mt8173-larb-port.h for mt8173, and
dt-binding/memory/mt8183-larb-port.h for mt8183.
Example:
iommu: iommu@10205000 {

View File

@@ -0,0 +1,65 @@
MediaTek GCE
===============
The Global Command Engine (GCE) is used to help read/write registers with
critical time limitation, such as updating display configuration during the
vblank. The GCE can be used to implement the Command Queue (CMDQ) driver.
CMDQ driver uses mailbox framework for communication. Please refer to
mailbox.txt for generic information about mailbox device-tree bindings.
Required properties:
- compatible: Must be "mediatek,mt8173-gce"
- reg: Address range of the GCE unit
- interrupts: The interrupt signal from the GCE block
- clock: Clocks according to the common clock binding
- clock-names: Must be "gce" to stand for GCE clock
- thread-num: Maximum threads count of GCE.
- #mbox-cells: Should be 4.
<&phandle channel timeout priority atomic_exec>
phandle: Label name of a gce node.
channel: Channel of mailbox. Be equal to the thread id of GCE.
timeout: Maximum time of software waiting GCE processing done, in unit
of millisecond.
priority: Priority of GCE thread.
atomic_exec: GCE processing continuous packets of commands in atomic
way.
Required properties for a client device:
- mboxes: Client use mailbox to communicate with GCE, it should have this
property and list of phandle, mailbox specifiers.
- gce-subsys: Specify the sub-system id which is corresponding to the register
address.
Optional properties for a client device:
- gce-event: Specify the event if the client has any. Because the event is
parsed by client, so client can replace 'gce-event' with other meaningful
name.
Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as
thread number, sub-system ids, thread priority, event ids.
Example:
gce: gce@10212000 {
compatible = "mediatek,mt8173-gce";
reg = <0 0x10212000 0 0x1000>;
interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg CLK_INFRA_GCE>;
clock-names = "gce";
thread-num = CMDQ_THR_MAX_COUNT;
#mbox-cells = <4>;
};
Example for a client device:
mmsys: clock-controller@14000000 {
compatible = "mediatek,mt8173-mmsys";
mboxes = <&gce 0 2000 CMDQ_THR_PRIO_LOWEST 1>,
<&gce 1 2000 CMDQ_THR_PRIO_LOWEST 1>;
gce-subsys = <SUBSYS_1400XXXX>;
mutex-event-eof = <CMDQ_EVENT_MUTEX0_STREAM_EOF
CMDQ_EVENT_MUTEX1_STREAM_EOF>;
...
};

View File

@@ -2,9 +2,10 @@ SMI (Smart Multimedia Interface) Common
The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
Mediatek SMI have two generations of HW architecture, mt2712 and mt8173 use
the second generation of SMI HW while mt2701 uses the first generation HW of
SMI.
Mediatek SMI have two generations of HW architecture, here is the list
which generation the Socs use:
generation 1: mt2701.
generation 2: mt2712, mt8173 and mt8183.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
@@ -18,6 +19,7 @@ Required properties:
"mediatek,mt2701-smi-common"
"mediatek,mt2712-smi-common"
"mediatek,mt8173-smi-common"
"mediatek,mt8183-smi-common"
- reg : the register and size of the SMI block.
- power-domains : a phandle to the power domain of this local arbiter.
- clocks : Must contain an entry for each entry in clock-names.
@@ -29,6 +31,11 @@ Required properties:
They may be the same if both source clocks are the same.
- "async" : asynchronous clock, it help transform the smi clock into the emi
clock domain, this clock is only needed by generation 1 smi HW.
and these 2 option clocks for generation 2 smi HW:
- "gals0": the path0 clock of GALS(Global Async Local Sync).
- "gals1": the path1 clock of GALS(Global Async Local Sync).
Note that "gals0" and "gals1" clock only exist while the SMI HW has "GALS"
modules.
Example:
smi_common: smi@14022000 {

View File

@@ -7,6 +7,7 @@ Required properties:
"mediatek,mt2701-smi-larb"
"mediatek,mt2712-smi-larb"
"mediatek,mt8173-smi-larb"
"mediatek,mt8183-smi-larb"
- reg : the register and size of this local arbiter.
- mediatek,smi : a phandle to the smi_common node.
- power-domains : a phandle to the power domain of this local arbiter.
@@ -15,6 +16,8 @@ Required properties:
- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
- "smi" : It's the clock for transfer data and command.
and this optional clock name:
- "gals": the clock for gals(Global Async Local Sync).
Required property for mt2701 and mt2712:
- mediatek,larb-id :the hardware id of this larb.

View File

@@ -14,6 +14,7 @@ Required properties:
"mediatek,mt2712-mmc": for mmc host ip compatible with mt2712
"mediatek,mt7622-mmc": for MT7622 SoC
"mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC
"mediatek,mt8183-mmc": for mmc host ip compatible with mt8183
- reg: physical base address of the controller and length
- interrupts: Should contain MSDC interrupt number

View File

@@ -1,13 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_MEDIATEK) += aiv8183m1v2.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += aiv8183m1v2-clkitg.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-clkitg.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb
ifeq ($(strip $(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE)), y)

View File

@@ -18,6 +18,7 @@
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt8173-power.h>
#include <dt-bindings/reset/mt8173-resets.h>
#include <dt-bindings/gce/mt8173-gce.h>
#include "mt8173-pinfunc.h"
/ {
@@ -429,6 +430,16 @@
status = "disabled";
};
gce: gce@10212000 {
compatible = "mediatek,mt8173-gce";
reg = <0 0x10212000 0 0x1000>;
interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg CLK_INFRA_GCE>;
clock-names = "gce";
thread-num = <CMDQ_THR_MAX_COUNT>;
#mbox-cells = <4>;
};
mipi_tx0: mipi-dphy@10215000 {
compatible = "mediatek,mt8173-mipi-tx";
reg = <0 0x10215000 0 0x1000>;

View File

@@ -1688,6 +1688,11 @@ static struct pdev_drv pderv[] = {
PDEV_DRV("clkdbg-pd8"),
PDEV_DRV("clkdbg-pd9"),
PDEV_DRV("clkdbg-pd10"),
PDEV_DRV("clkdbg-pd11"),
PDEV_DRV("clkdbg-pd12"),
PDEV_DRV("clkdbg-pd13"),
PDEV_DRV("clkdbg-pd14"),
PDEV_DRV("clkdbg-pd15"),
};
static void reg_pdev_drv(const char *pdname, struct seq_file *s)

View File

@@ -13,6 +13,8 @@ mediatek-drm-y := mtk_disp_color.o \
mtk_mipi_tx.o \
mtk_dpi.o
mediatek-drm-$(CONFIG_DRM_FBDEV_EMULATION) += mtk_drm_fbdev.o
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
mediatek-drm-hdmi-objs := mtk_cec.o \

View File

@@ -30,6 +30,7 @@
#include "mtk_drm_ddp_comp.h"
#include "mtk_drm_drv.h"
#include "mtk_drm_fb.h"
#include "mtk_drm_fbdev.h"
#include "mtk_drm_gem.h"
#define DRIVER_NAME "mediatek"
@@ -127,10 +128,20 @@ static int mtk_atomic_commit(struct drm_device *drm,
return 0;
}
static void mtk_drm_mode_output_poll_changed(struct drm_device *dev)
{
struct mtk_drm_private *priv = dev->dev_private;
struct drm_fb_helper *fb_helper = &priv->fb_helper;
if (fb_helper)
drm_fb_helper_hotplug_event(fb_helper);
}
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
.fb_create = mtk_drm_mode_fb_create,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = mtk_atomic_commit,
.output_poll_changed = mtk_drm_mode_output_poll_changed,
};
static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
@@ -257,8 +268,14 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm_kms_helper_poll_init(drm);
drm_mode_config_reset(drm);
ret = mtk_fbdev_init(drm);
if (ret)
goto err_kms_helper_poll_fini;
return 0;
err_kms_helper_poll_fini:
drm_kms_helper_poll_fini(drm);
err_component_unbind:
component_unbind_all(drm->dev, drm);
err_config_cleanup:
@@ -269,6 +286,7 @@ err_config_cleanup:
static void mtk_drm_kms_deinit(struct drm_device *drm)
{
mtk_fbdev_fini(drm);
drm_kms_helper_poll_fini(drm);
component_unbind_all(drm->dev, drm);

View File

@@ -14,6 +14,7 @@
#ifndef MTK_DRM_DRV_H
#define MTK_DRM_DRV_H
#include <drm/drm_fb_helper.h>
#include <linux/io.h>
#include "mtk_drm_ddp_comp.h"
@@ -24,7 +25,6 @@ struct device;
struct device_node;
struct drm_crtc;
struct drm_device;
struct drm_fb_helper;
struct drm_property;
struct regmap;
@@ -56,6 +56,8 @@ struct mtk_drm_private {
} commit;
struct drm_atomic_state *suspend_state;
struct drm_fb_helper fb_helper;
struct drm_gem_object *fbdev_bo;
};
extern struct platform_driver mtk_ddp_driver;

View File

@@ -96,6 +96,19 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev,
return mtk_fb;
}
struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode,
struct drm_gem_object *obj)
{
struct mtk_drm_fb *mtk_fb;
mtk_fb = mtk_drm_framebuffer_init(dev, mode, obj);
if (IS_ERR(mtk_fb))
return ERR_CAST(mtk_fb);
return &mtk_fb->base;
}
/*
* Wait for any exclusive fence in fb's gem object's reservation object.
*

View File

@@ -19,5 +19,8 @@ int mtk_fb_wait(struct drm_framebuffer *fb);
struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *cmd);
struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode,
struct drm_gem_object *obj);
#endif /* MTK_DRM_FB_H */

View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2016 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 <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include "mtk_drm_drv.h"
#include "mtk_drm_fb.h"
#include "mtk_drm_gem.h"
#define to_drm_private(x) \
container_of(x, struct mtk_drm_private, fb_helper)
static int mtk_drm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *helper = info->par;
struct mtk_drm_private *private = to_drm_private(helper);
return mtk_drm_gem_mmap_buf(private->fbdev_bo, vma);
}
static struct fb_ops mtk_fbdev_ops = {
.owner = THIS_MODULE,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_blank = drm_fb_helper_blank,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_setcmap = drm_fb_helper_setcmap,
.fb_mmap = mtk_drm_fbdev_mmap,
};
static int mtk_fbdev_probe(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = helper->dev;
struct mtk_drm_private *private = to_drm_private(helper);
struct drm_mode_fb_cmd2 mode = { 0 };
struct mtk_drm_gem_obj *mtk_gem;
struct fb_info *info;
struct drm_framebuffer *fb;
unsigned int bytes_per_pixel;
unsigned long offset;
size_t size;
int err;
bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
mode.width = sizes->surface_width;
mode.height = sizes->surface_height;
mode.pitches[0] = sizes->surface_width * bytes_per_pixel;
mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
size = mode.pitches[0] * mode.height;
mtk_gem = mtk_drm_gem_create(dev, size, true);
if (IS_ERR(mtk_gem))
return PTR_ERR(mtk_gem);
private->fbdev_bo = &mtk_gem->base;
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) {
err = PTR_ERR(info);
dev_err(dev->dev, "failed to allocate framebuffer info, %d\n",
err);
goto err_gem_free_object;
}
fb = mtk_drm_framebuffer_create(dev, &mode, private->fbdev_bo);
if (IS_ERR(fb)) {
err = PTR_ERR(fb);
dev_err(dev->dev, "failed to allocate DRM framebuffer, %d\n",
err);
goto err_release_fbi;
}
helper->fb = fb;
info->par = helper;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &mtk_fbdev_ops;
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
drm_fb_helper_fill_var(info, helper, sizes->fb_width, sizes->fb_height);
offset = info->var.xoffset * bytes_per_pixel;
offset += info->var.yoffset * fb->pitches[0];
dev->mode_config.fb_base = 0;
info->screen_base = mtk_gem->kvaddr + offset;
info->screen_size = size;
info->fix.smem_len = size;
DRM_DEBUG_KMS("FB [%ux%u]-%u offset=%lu size=%zd\n",
fb->width, fb->height, fb->format->depth, offset, size);
info->skip_vt_switch = true;
return 0;
err_release_fbi:
err_gem_free_object:
mtk_drm_gem_free_object(&mtk_gem->base);
return err;
}
static const struct drm_fb_helper_funcs mtk_drm_fb_helper_funcs = {
.fb_probe = mtk_fbdev_probe,
};
int mtk_fbdev_init(struct drm_device *dev)
{
struct mtk_drm_private *priv = dev->dev_private;
struct drm_fb_helper *helper = &priv->fb_helper;
int ret;
if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
return -EINVAL;
drm_fb_helper_prepare(dev, helper, &mtk_drm_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper,
dev->mode_config.num_connector);
if (ret) {
dev_err(dev->dev, "failed to initialize DRM FB helper, %d\n",
ret);
goto fini;
}
ret = drm_fb_helper_single_add_all_connectors(helper);
if (ret) {
dev_err(dev->dev, "failed to add connectors, %d\n", ret);
goto fini;
}
/* disable all the possible outputs/crtcs before entering KMS mode */
if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(helper, 32);
if (ret) {
dev_err(dev->dev, "failed to set initial configuration, %d\n",
ret);
goto fini;
}
return 0;
fini:
drm_fb_helper_fini(helper);
return ret;
}
void mtk_fbdev_fini(struct drm_device *dev)
{
struct mtk_drm_private *priv = dev->dev_private;
struct drm_fb_helper *helper = &priv->fb_helper;
drm_fb_helper_unregister_fbi(helper);
if (helper->fb) {
drm_framebuffer_unregister_private(helper->fb);
drm_framebuffer_remove(helper->fb);
}
drm_fb_helper_fini(helper);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2016 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.
*/
#ifndef MTK_DRM_FBDEV_H
#define MTK_DRM_FBDEV_H
#ifdef CONFIG_DRM_FBDEV_EMULATION
int mtk_fbdev_init(struct drm_device *dev);
void mtk_fbdev_fini(struct drm_device *dev);
#else
int mtk_fbdev_init(struct drm_device *dev)
{
return 0;
}
void mtk_fbdev_fini(struct drm_device *dev)
{
}
#endif /* CONFIG_DRM_FBDEV_EMULATION */
#endif /* MTK_DRM_FBDEV_H */

View File

@@ -124,7 +124,9 @@
#define ARM_V7S_TEX_MASK 0x7
#define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)
#define ARM_V7S_ATTR_MTK_4GB BIT(9) /* MTK extend it for 4GB mode */
/* MTK extend the two bits below for over 4GB mode */
#define ARM_V7S_ATTR_MTK_PA_BIT32 BIT(9)
#define ARM_V7S_ATTR_MTK_PA_BIT33 BIT(4)
/* *well, except for TEX on level 2 large pages, of course :( */
#define ARM_V7S_CONT_PAGE_TEX_SHIFT 6
@@ -263,7 +265,8 @@ static void __arm_v7s_set_pte(arm_v7s_iopte *ptep, arm_v7s_iopte pte,
}
static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
struct io_pgtable_cfg *cfg)
struct io_pgtable_cfg *cfg,
phys_addr_t paddr) /* Only for MTK */
{
bool ap = !(cfg->quirks & IO_PGTABLE_QUIRK_NO_PERMS);
arm_v7s_iopte pte = ARM_V7S_ATTR_NG | ARM_V7S_ATTR_S;
@@ -290,8 +293,12 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS))
pte |= ARM_V7S_ATTR_NS_SECTION;
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)
pte |= ARM_V7S_ATTR_MTK_4GB;
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
if (paddr & BIT_ULL(32))
pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
if (paddr & BIT_ULL(33))
pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
}
return pte;
}
@@ -387,7 +394,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
return -EEXIST;
}
pte = arm_v7s_prot_to_pte(prot, lvl, cfg);
pte = arm_v7s_prot_to_pte(prot, lvl, cfg, paddr);
if (num_entries > 1)
pte = arm_v7s_pte_to_cont(pte, lvl);
@@ -479,7 +486,11 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;
if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
if (WARN_ON(upper_32_bits(iova)))
return -ERANGE;
if (WARN_ON(upper_32_bits(paddr) &&
!(iop->cfg.quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)))
return -ERANGE;
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
@@ -557,7 +568,7 @@ static int arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
num_entries = size >> ARM_V7S_LVL_SHIFT(2);
unmap_idx = ARM_V7S_LVL_IDX(iova, 2);
pte = arm_v7s_prot_to_pte(arm_v7s_pte_to_prot(blk_pte, 1), 2, cfg);
pte = arm_v7s_prot_to_pte(arm_v7s_pte_to_prot(blk_pte, 1), 2, cfg, 0);
if (num_entries > 1)
pte = arm_v7s_pte_to_cont(pte, 2);
@@ -671,7 +682,9 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
unsigned long iova)
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
struct io_pgtable_cfg *cfg = &data->iop.cfg;
arm_v7s_iopte *ptep = data->pgd, pte;
phys_addr_t paddr;
int lvl = 0;
u32 mask;
@@ -687,7 +700,16 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
mask = ARM_V7S_LVL_MASK(lvl);
if (arm_v7s_pte_is_cont(pte, lvl))
mask *= ARM_V7S_CONT_PAGES;
return (pte & mask) | (iova & ~mask);
paddr = (pte & mask) | (iova & ~mask);
if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) &&
cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
paddr |= BIT_ULL(32);
if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
paddr |= BIT_ULL(33);
}
return paddr;
}
static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,

View File

@@ -62,10 +62,10 @@ struct io_pgtable_cfg {
* (unmapped) entries but the hardware might do so anyway, perform
* TLB maintenance when mapping as well as when unmapping.
*
* IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all
* PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
* when the SoC is in "4GB mode" and they can only access the high
* remap of DRAM (0x1_00000000 to 0x1_ffffffff).
* IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 4 and 9 in all
* PTEs, for Mediatek IOMMUs which treat it as the 33rd and 32rd
* address bit when the SoC dram is over 4GB and they can access
* the physical address from 0x4000_0000 to 0x3_ffff_ffff.
*
* IO_PGTABLE_QUIRK_NO_DMA: Guarantees that the tables will only ever
* be accessed by a fully cache-coherent IOMMU or CPU (e.g. for a

View File

@@ -36,6 +36,7 @@
#include "mtk_iommu.h"
#define REG_MMU_PT_BASE_ADDR 0x000
#define MMU_PT_ADDR_MASK GENMASK(31, 7)
#define REG_MMU_INVALIDATE 0x020
#define F_ALL_INVLD 0x2
@@ -54,7 +55,7 @@
#define REG_MMU_CTRL_REG 0x110
#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
((data)->plat_data->m4u_plat == M4U_MT8173 ? 5 : 4)
/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
#define F_MMU_TF_PROTECT_SEL(prot, data) \
(((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
@@ -73,27 +74,32 @@
#define F_MISS_FIFO_ERR_INT_EN BIT(6)
#define F_INT_CLR_BIT BIT(12)
#define REG_MMU_INT_MAIN_CONTROL 0x124
#define F_INT_TRANSLATION_FAULT BIT(0)
#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
#define F_INT_INVALID_PA_FAULT BIT(2)
#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
#define F_INT_TLB_MISS_FAULT BIT(4)
#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
#define REG_MMU_INT_MAIN_CONTROL 0x124 /* mmu0 | mmu1 */
#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))
#define REG_MMU_CPE_DONE 0x12C
#define REG_MMU_FAULT_ST1 0x134
#define F_REG_MMU0_FAULT_MASK GENMASK(6, 0)
#define F_REG_MMU1_FAULT_MASK GENMASK(13, 7)
#define REG_MMU_FAULT_VA 0x13c
#define REG_MMU0_FAULT_VA 0x13c
#define F_MMU_FAULT_VA_WRITE_BIT BIT(1)
#define F_MMU_FAULT_VA_LAYER_BIT BIT(0)
#define REG_MMU_INVLD_PA 0x140
#define REG_MMU_INT_ID 0x150
#define F_MMU0_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
#define F_MMU0_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
#define REG_MMU0_INVLD_PA 0x140
#define REG_MMU1_FAULT_VA 0x144
#define REG_MMU1_INVLD_PA 0x148
#define REG_MMU0_INT_ID 0x150
#define REG_MMU1_INT_ID 0x154
#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
#define MTK_PROTECT_PA_ALIGN 128
@@ -202,6 +208,17 @@ static const struct iommu_gather_ops mtk_iommu_gather_ops = {
.tlb_sync = mtk_iommu_tlb_sync,
};
static unsigned int mtk_iommu_get_larbid(const unsigned int *larbid_in_common,
const unsigned int fault_larb)
{
int i;
for (i = 0; i < MTK_LARB_NR_MAX; i++)
if (larbid_in_common[i] == fault_larb)
return i;
return MTK_LARB_NR_MAX; /* Invalid larb id. */
}
static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
{
struct mtk_iommu_data *data = dev_id;
@@ -212,14 +229,24 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
/* Read error info from registers */
int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
if (int_state & F_REG_MMU0_FAULT_MASK) {
regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
} else {
regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
}
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
regval = readl_relaxed(data->base + REG_MMU_INT_ID);
fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
fault_port = F_MMU0_INT_ID_PORT_ID(regval);
fault_larb = F_MMU_INT_ID_LARB_ID(regval);
fault_port = F_MMU_INT_ID_PORT_ID(regval);
if (data->plat_data->larbid_remap_enable)
fault_larb = mtk_iommu_get_larbid(
data->plat_data->larbid_in_common,
fault_larb);
if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
@@ -344,7 +371,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) {
data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr[0],
writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
data->base + REG_MMU_PT_BASE_ADDR);
}
@@ -367,12 +394,17 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
unsigned long flags;
int ret;
if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) &&
data->plat_data->has_4gb_mode &&
data->enable_4GB)
paddr |= BIT_ULL(32);
spin_lock_irqsave(&dom->pgtlock, flags);
ret = dom->iop->map(dom->iop, iova, paddr & DMA_BIT_MASK(32),
size, prot);
ret = dom->iop->map(dom->iop, iova, paddr, size, prot);
spin_unlock_irqrestore(&dom->pgtlock, flags);
return ret;
@@ -401,7 +433,6 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
unsigned long flags;
phys_addr_t pa;
@@ -409,9 +440,6 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
pa = dom->iop->iova_to_phys(dom->iop, iova);
spin_unlock_irqrestore(&dom->pgtlock, flags);
if (data->enable_4GB)
pa |= BIT_ULL(32);
return pa;
}
@@ -508,6 +536,7 @@ static struct iommu_ops mtk_iommu_ops = {
static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
{
enum mtk_iommu_plat m4u_plat = data->plat_data->m4u_plat;
u32 regval;
int ret;
@@ -518,7 +547,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
regval = F_MMU_TF_PROTECT_SEL(2, data);
if (data->m4u_plat == M4U_MT8173)
if (m4u_plat == M4U_MT8173)
regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
@@ -539,14 +568,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
if (data->m4u_plat == M4U_MT8173)
if (m4u_plat == M4U_MT8173)
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
upper_32_bits(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
if (data->enable_4GB && m4u_plat == M4U_MT2712) {
/*
* If 4GB mode is enabled, the validate PA range is from
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -556,8 +585,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
/* It's MISC control register whose default value is ok except mt8173.*/
if (data->m4u_plat == M4U_MT8173)
/*
* It's MISC control register whose default value is ok
* except mt8173 and mt8183.
*/
if (m4u_plat == M4U_MT8173 || m4u_plat == M4U_MT8183)
writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -590,7 +622,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->dev = dev;
data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
data->plat_data = of_device_get_match_data(dev);
/* Protect memory. HW will access here while translation fault.*/
protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -612,7 +644,9 @@ static int mtk_iommu_probe(struct platform_device *pdev)
return data->irq;
data->bclk = devm_clk_get(dev, "bclk");
if (IS_ERR(data->bclk))
if (PTR_ERR(data->bclk) == -ENOENT)
data->bclk = NULL;
else if (IS_ERR(data->bclk))
return PTR_ERR(data->bclk);
larb_nr = of_count_phandle_with_args(dev->of_node,
@@ -688,6 +722,11 @@ static int mtk_iommu_remove(struct platform_device *pdev)
return 0;
}
static void mtk_iommu_shutdown(struct platform_device *pdev)
{
mtk_iommu_remove(pdev);
}
static int __maybe_unused mtk_iommu_suspend(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
@@ -701,6 +740,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
reg->vld_pa_range = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
clk_disable_unprepare(data->bclk);
return 0;
}
@@ -709,6 +749,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
struct mtk_iommu_domain *dom = data->m4u_dom;
void __iomem *base = data->base;
int ret;
@@ -724,8 +765,9 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
if (data->m4u_dom)
writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
writel_relaxed(reg->vld_pa_range, base + REG_MMU_VLD_PA_RNG);
if (dom)
writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
base + REG_MMU_PT_BASE_ADDR);
return 0;
}
@@ -734,15 +776,33 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
};
static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
.has_4gb_mode = true,
};
static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
.has_4gb_mode = true,
};
static const struct mtk_iommu_plat_data mt8183_data = {
.m4u_plat = M4U_MT8183,
.larbid_remap_enable = true,
.larbid_in_common = {0, 7, 5, 6, 1, 2, 3, 4},
};
static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
{ .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
{ .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
{ .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
{ .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
{}
};
static struct platform_driver mtk_iommu_driver = {
.probe = mtk_iommu_probe,
.remove = mtk_iommu_remove,
.shutdown = mtk_iommu_shutdown,
.driver = {
.name = "mtk-iommu",
.of_match_table = of_match_ptr(mtk_iommu_of_ids),

View File

@@ -33,12 +33,23 @@ struct mtk_iommu_suspend_reg {
u32 int_control0;
u32 int_main_control;
u32 ivrp_paddr;
u32 vld_pa_range;
};
enum mtk_iommu_plat {
M4U_MT2701,
M4U_MT2712,
M4U_MT8173,
M4U_MT8183,
};
struct mtk_iommu_plat_data {
enum mtk_iommu_plat m4u_plat;
bool has_4gb_mode;
/* The larb-id may be remapped in the smi-common. */
bool larbid_remap_enable;
unsigned int larbid_in_common[MTK_LARB_NR_MAX];
};
struct mtk_iommu_domain;
@@ -53,11 +64,11 @@ struct mtk_iommu_data {
struct mtk_iommu_domain *m4u_dom;
struct iommu_group *m4u_group;
struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
bool enable_4GB;
bool enable_4GB; /* Dram is over 4gb */
bool tlb_flush_active;
struct iommu_device iommu;
enum mtk_iommu_plat m4u_plat;
const struct mtk_iommu_plat_data *plat_data;
struct list_head list;
};

View File

@@ -172,7 +172,7 @@ config BCM_FLEXRM_MBOX
SoCs. Say Y here if you want to use the Broadcom FlexRM.
config MTK_CMDQ_MBOX
bool "MediaTek CMDQ Mailbox Support"
tristate "MediaTek CMDQ Mailbox Support"
help
Say yes here to add support for the MediaTek Command Queue (CMDQ)
mailbox driver. The CMDQ is used to help read/write registers with

View File

@@ -37,4 +37,4 @@ obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o
obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o
obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o

View File

@@ -49,6 +49,24 @@
#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
#define F_MMU_EN BIT(0)
/* SMI COMMON */
#define SMI_BUS_SEL 0x220
#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
/* All are MMU0 defaultly. Only specialize mmu1 here. */
#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
enum mtk_smi_gen {
MTK_SMI_GEN1,
MTK_SMI_GEN2
};
struct mtk_smi_common_plat {
enum mtk_smi_gen gen;
/* Adjust some larbs to mmu1 to balance the bandwidth */
unsigned int bus_sel;
};
struct mtk_smi_larb_gen {
bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
@@ -58,8 +76,11 @@ struct mtk_smi_larb_gen {
struct mtk_smi {
struct device *dev;
struct clk *clk_apb, *clk_smi;
struct clk *clk_gals0, *clk_gals1;
struct clk *clk_async; /*only needed by mt2701*/
void __iomem *smi_ao_base;
void __iomem *smi_ao_base; /* only for gen1 */
void __iomem *base; /* only for gen2 */
const struct mtk_smi_common_plat *plat;
};
struct mtk_smi_larb { /* larb: local arbiter */
@@ -71,82 +92,56 @@ struct mtk_smi_larb { /* larb: local arbiter */
u32 *mmu;
};
enum mtk_smi_gen {
MTK_SMI_GEN1,
MTK_SMI_GEN2
};
static int mtk_smi_enable(const struct mtk_smi *smi)
static int mtk_smi_clk_enable(const struct mtk_smi *smi)
{
int ret;
ret = pm_runtime_get_sync(smi->dev);
if (ret < 0)
return ret;
ret = clk_prepare_enable(smi->clk_apb);
if (ret)
goto err_put_pm;
return ret;
ret = clk_prepare_enable(smi->clk_smi);
if (ret)
goto err_disable_apb;
ret = clk_prepare_enable(smi->clk_gals0);
if (ret)
goto err_disable_smi;
ret = clk_prepare_enable(smi->clk_gals1);
if (ret)
goto err_disable_gals0;
return 0;
err_disable_gals0:
clk_disable_unprepare(smi->clk_gals0);
err_disable_smi:
clk_disable_unprepare(smi->clk_smi);
err_disable_apb:
clk_disable_unprepare(smi->clk_apb);
err_put_pm:
pm_runtime_put_sync(smi->dev);
return ret;
}
static void mtk_smi_disable(const struct mtk_smi *smi)
static void mtk_smi_clk_disable(const struct mtk_smi *smi)
{
clk_disable_unprepare(smi->clk_gals1);
clk_disable_unprepare(smi->clk_gals0);
clk_disable_unprepare(smi->clk_smi);
clk_disable_unprepare(smi->clk_apb);
pm_runtime_put_sync(smi->dev);
}
int mtk_smi_larb_get(struct device *larbdev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
int ret;
int ret = pm_runtime_get_sync(larbdev);
/* Enable the smi-common's power and clocks */
ret = mtk_smi_enable(common);
if (ret)
return ret;
/* Enable the larb's power and clocks */
ret = mtk_smi_enable(&larb->smi);
if (ret) {
mtk_smi_disable(common);
return ret;
}
/* Configure the iommu info for this larb */
larb_gen->config_port(larbdev);
return 0;
return (ret < 0) ? ret : 0;
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
void mtk_smi_larb_put(struct device *larbdev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
/*
* Don't de-configure the iommu info for this larb since there may be
* several modules in this larb.
* The iommu info will be reset after power off.
*/
mtk_smi_disable(&larb->smi);
mtk_smi_disable(common);
pm_runtime_put_sync(larbdev);
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
@@ -176,12 +171,23 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
return -ENODEV;
}
static void mtk_smi_larb_config_port_mt2712(struct device *dev)
static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
u32 reg;
int i;
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
reg |= F_MMU_EN;
writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
}
}
static void mtk_smi_larb_config_port_mt2712(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
/*
* larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
* Don't need to set it again.
@@ -189,11 +195,7 @@ static void mtk_smi_larb_config_port_mt2712(struct device *dev)
if (larb->larbid == 8 || larb->larbid == 9)
return;
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
reg |= F_MMU_EN;
writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
}
mtk_smi_larb_config_port_gen2_general(dev);
}
static void mtk_smi_larb_config_port_mt8173(struct device *dev)
@@ -264,6 +266,10 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
.config_port = mtk_smi_larb_config_port_mt2712,
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
.config_port = mtk_smi_larb_config_port_gen2_general,
};
static const struct of_device_id mtk_smi_larb_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-larb",
@@ -277,6 +283,10 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
.compatible = "mediatek,mt2712-smi-larb",
.data = &mtk_smi_larb_mt2712
},
{
.compatible = "mediatek,mt8183-smi-larb",
.data = &mtk_smi_larb_mt8183
},
{}
};
@@ -306,6 +316,12 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
larb->smi.clk_smi = devm_clk_get(dev, "smi");
if (IS_ERR(larb->smi.clk_smi))
return PTR_ERR(larb->smi.clk_smi);
larb->smi.clk_gals0 = devm_clk_get(dev, "gals");
if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT)
larb->smi.clk_gals0 = NULL;
else if (IS_ERR(larb->smi.clk_gals0))
return PTR_ERR(larb->smi.clk_gals0);
larb->smi.dev = dev;
if (larb->larb_gen->need_larbid) {
@@ -344,27 +360,85 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
int ret;
/* Power on smi-common. */
ret = pm_runtime_get_sync(larb->smi_common_dev);
if (ret < 0) {
dev_err(dev, "smi-common pm get failed(%d).\n", ret);
return ret;
}
ret = mtk_smi_clk_enable(&larb->smi);
if (ret < 0) {
dev_err(dev, "larb clk enable failed(%d).\n", ret);
pm_runtime_put_sync(larb->smi_common_dev);
return ret;
}
/* Configure the basic setting for this larb */
larb_gen->config_port(dev);
return 0;
}
static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
mtk_smi_clk_disable(&larb->smi);
pm_runtime_put_sync(larb->smi_common_dev);
return 0;
}
static const struct dev_pm_ops smi_larb_pm_ops = {
SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
};
static struct platform_driver mtk_smi_larb_driver = {
.probe = mtk_smi_larb_probe,
.remove = mtk_smi_larb_remove,
.driver = {
.name = "mtk-smi-larb",
.of_match_table = mtk_smi_larb_of_ids,
.pm = &smi_larb_pm_ops,
}
};
static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
.gen = MTK_SMI_GEN1,
};
static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
.gen = MTK_SMI_GEN2,
};
static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
.gen = MTK_SMI_GEN2,
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(4) |
F_MMU1_LARB(7),
};
static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
.data = (void *)MTK_SMI_GEN2
.data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt2701-smi-common",
.data = (void *)MTK_SMI_GEN1
.data = &mtk_smi_common_gen1,
},
{
.compatible = "mediatek,mt2712-smi-common",
.data = (void *)MTK_SMI_GEN2
.data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt8183-smi-common",
.data = &mtk_smi_common_mt8183,
},
{}
};
@@ -374,13 +448,13 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct mtk_smi *common;
struct resource *res;
enum mtk_smi_gen smi_gen;
int ret;
common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
if (!common)
return -ENOMEM;
common->dev = dev;
common->plat = of_device_get_match_data(dev);
common->clk_apb = devm_clk_get(dev, "apb");
if (IS_ERR(common->clk_apb))
@@ -390,14 +464,25 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
if (IS_ERR(common->clk_smi))
return PTR_ERR(common->clk_smi);
common->clk_gals0 = devm_clk_get(dev, "gals0");
if (PTR_ERR(common->clk_gals0) == -ENOENT)
common->clk_gals0 = NULL;
else if (IS_ERR(common->clk_gals0))
return PTR_ERR(common->clk_gals0);
common->clk_gals1 = devm_clk_get(dev, "gals1");
if (PTR_ERR(common->clk_gals1) == -ENOENT)
common->clk_gals1 = NULL;
else if (IS_ERR(common->clk_gals1))
return PTR_ERR(common->clk_gals1);
/*
* for mtk smi gen 1, we need to get the ao(always on) base to config
* m4u port, and we need to enable the aync clock for transform the smi
* clock into emi clock domain, but for mtk smi gen2, there's no smi ao
* base.
*/
smi_gen = (enum mtk_smi_gen)of_device_get_match_data(dev);
if (smi_gen == MTK_SMI_GEN1) {
if (common->plat->gen == MTK_SMI_GEN1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
common->smi_ao_base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->smi_ao_base))
@@ -410,6 +495,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
ret = clk_prepare_enable(common->clk_async);
if (ret)
return ret;
} else {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
common->base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->base))
return PTR_ERR(common->base);
}
pm_runtime_enable(dev);
platform_set_drvdata(pdev, common);
@@ -422,12 +512,40 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused mtk_smi_common_resume(struct device *dev)
{
struct mtk_smi *common = dev_get_drvdata(dev);
unsigned int bus_sel = common->plat->bus_sel;
int ret;
ret = mtk_smi_clk_enable(common);
if (ret)
return ret;
if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
writel(bus_sel, common->base + SMI_BUS_SEL);
return 0;
}
static int __maybe_unused mtk_smi_common_suspend(struct device *dev)
{
struct mtk_smi *common = dev_get_drvdata(dev);
mtk_smi_clk_disable(common);
return 0;
}
static const struct dev_pm_ops smi_common_pm_ops = {
SET_RUNTIME_PM_OPS(mtk_smi_common_suspend, mtk_smi_common_resume, NULL)
};
static struct platform_driver mtk_smi_common_driver = {
.probe = mtk_smi_common_probe,
.remove = mtk_smi_common_remove,
.driver = {
.name = "mtk-smi-common",
.of_match_table = mtk_smi_common_of_ids,
.pm = &smi_common_pm_ops,
}
};
@@ -454,3 +572,6 @@ err_unreg_smi:
}
module_init(mtk_smi_init);
MODULE_DESCRIPTION("MediaTek SMI driver");
MODULE_LICENSE("GPL v2");

View File

@@ -21,15 +21,21 @@
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/core.h>
#include <linux/mfd/mt6397/registers.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/mfd/mt6323/registers.h>
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
#define MT6323_CID_CODE 0x23
#define MT6358_CID_CODE 0x20
#define MT6391_CID_CODE 0x91
#define MT6397_CID_CODE 0x97
struct chip_data {
u32 cid_addr;
};
static const struct resource mt6397_rtc_resources[] = {
{
.start = MT6397_RTC_BASE,
@@ -43,6 +49,16 @@ static const struct resource mt6397_rtc_resources[] = {
},
};
static const struct resource mt6323_keys_resources[] = {
DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY),
DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY),
};
static const struct resource mt6397_keys_resources[] = {
DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY),
DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY),
};
static const struct mfd_cell mt6323_devs[] = {
{
.name = "mt6323-regulator",
@@ -50,6 +66,18 @@ static const struct mfd_cell mt6323_devs[] = {
}, {
.name = "mt6323-led",
.of_compatible = "mediatek,mt6323-led"
}, {
.name = "mtk-pmic-keys",
.num_resources = ARRAY_SIZE(mt6323_keys_resources),
.resources = mt6323_keys_resources,
.of_compatible = "mediatek,mt6323-keys"
},
};
static const struct mfd_cell mt6358_devs[] = {
{
.name = "mt6358-regulator",
.of_compatible = "mediatek,mt6358-regulator"
},
};
@@ -71,7 +99,24 @@ static const struct mfd_cell mt6397_devs[] = {
}, {
.name = "mt6397-pinctrl",
.of_compatible = "mediatek,mt6397-pinctrl",
},
}, {
.name = "mtk-pmic-keys",
.num_resources = ARRAY_SIZE(mt6397_keys_resources),
.resources = mt6397_keys_resources,
.of_compatible = "mediatek,mt6397-keys"
}
};
static const struct chip_data mt6323_core = {
.cid_addr = MT6397_CID,
};
static const struct chip_data mt6358_core = {
.cid_addr = MT6358_SWCID,
};
static const struct chip_data mt6397_core = {
.cid_addr = MT6397_CID,
};
static void mt6397_irq_lock(struct irq_data *data)
@@ -250,6 +295,7 @@ static int mt6397_probe(struct platform_device *pdev)
int ret;
unsigned int id;
struct mt6397_chip *pmic;
const struct chip_data *pmic_core;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
@@ -267,7 +313,11 @@ static int mt6397_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmic);
ret = regmap_read(pmic->regmap, MT6397_CID, &id);
pmic_core = of_device_get_match_data(&pdev->dev);
if (!pmic_core)
return -ENODEV;
ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
if (ret) {
dev_err(pmic->dev, "Failed to read chip id: %d\n", ret);
return ret;
@@ -289,7 +339,21 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL,
0, NULL);
0, pmic->irq_domain);
break;
case MT6358_CID_CODE:
pmic->int_con[0] = MT6358_PSC_TOP_INT_CON0;
pmic->int_con[1] = MT6358_HK_TOP_INT_CON0;
pmic->int_status[0] = MT6358_PSC_TOP_INT_STATUS0;
pmic->int_status[1] = MT6358_HK_TOP_INT_STATUS0;
ret = mt6397_irq_init(pmic);
if (ret)
return ret;
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6358_devs,
ARRAY_SIZE(mt6358_devs), NULL,
0, pmic->irq_domain);
break;
case MT6397_CID_CODE:
@@ -304,7 +368,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL,
0, NULL);
0, pmic->irq_domain);
break;
default:
@@ -322,9 +386,18 @@ static int mt6397_probe(struct platform_device *pdev)
}
static const struct of_device_id mt6397_of_match[] = {
{ .compatible = "mediatek,mt6397" },
{ .compatible = "mediatek,mt6323" },
{ }
{
.compatible = "mediatek,mt6323",
.data = &mt6323_core,
}, {
.compatible = "mediatek,mt6358",
.data = &mt6358_core,
}, {
.compatible = "mediatek,mt6397",
.data = &mt6397_core,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, mt6397_of_match);

View File

@@ -85,6 +85,13 @@
#define EMMC50_CFG3 0x220
#define SDC_FIFO_CFG 0x228
/*--------------------------------------------------------------------------*/
/* Top Register Offset */
/*--------------------------------------------------------------------------*/
#define EMMC_TOP_CONTROL (0x00)
#define EMMC_TOP_CMD (0x04)
#define EMMC50_PAD_DS_TUNE (0x0c)
/*--------------------------------------------------------------------------*/
/* Register Mask */
/*--------------------------------------------------------------------------*/
@@ -260,6 +267,23 @@
#define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */
#define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */
/* EMMC_TOP_CONTROL mask */
#define PAD_RXDLY_SEL (0x1 << 0) /* RW */
#define DELAY_EN (0x1 << 1) /* RW */
#define PAD_DAT_RD_RXDLY2 (0x1F << 2) /* RW */
#define PAD_DAT_RD_RXDLY (0x1F << 7) /* RW */
#define PAD_DAT_RD_RXDLY2_SEL (0x1 << 12) /* RW */
#define PAD_DAT_RD_RXDLY_SEL (0x1 << 13) /* RW */
#define DATA_K_VALUE_SEL (0x1 << 14) /* RW */
#define SDC_RX_ENH_EN (0x1 << 15) /* TW */
/* EMMC_TOP_CMD mask */
#define PAD_CMD_RXDLY2 (0x1F << 0) /* RW */
#define PAD_CMD_RXDLY (0x1F << 5) /* RW */
#define PAD_CMD_RD_RXDLY2_SEL (0x1 << 10) /* RW */
#define PAD_CMD_RD_RXDLY_SEL (0x1 << 11) /* RW */
#define PAD_CMD_TX_DLY (0x1F << 12) /* RW */
#define REQ_CMD_EIO (0x1 << 0)
#define REQ_CMD_TMO (0x1 << 1)
#define REQ_DAT_ERR (0x1 << 2)
@@ -332,6 +356,9 @@ struct msdc_save_para {
u32 emmc50_cfg0;
u32 emmc50_cfg3;
u32 sdc_fifo_cfg;
u32 emmc_top_control;
u32 emmc_top_cmd;
u32 emmc50_pad_ds_tune;
};
struct mtk_mmc_compatible {
@@ -344,12 +371,15 @@ struct mtk_mmc_compatible {
bool stop_clk_fix;
bool enhance_rx;
bool support_64g;
bool tune_resp_data_together;
};
struct msdc_tune_para {
u32 iocon;
u32 pad_tune;
u32 pad_cmd_tune;
u32 emmc_top_control;
u32 emmc_top_cmd;
};
struct msdc_delay_phase {
@@ -371,6 +401,7 @@ struct msdc_host {
int error;
void __iomem *base; /* host base address */
void __iomem *top_base; /* host top register base address */
struct msdc_dma dma; /* dma channel */
u64 dma_mask;
@@ -414,6 +445,7 @@ static const struct mtk_mmc_compatible mt8135_compat = {
.stop_clk_fix = false,
.enhance_rx = false,
.support_64g = false,
.tune_resp_data_together = false,
};
static const struct mtk_mmc_compatible mt8173_compat = {
@@ -426,6 +458,7 @@ static const struct mtk_mmc_compatible mt8173_compat = {
.stop_clk_fix = false,
.enhance_rx = false,
.support_64g = false,
.tune_resp_data_together = false,
};
static const struct mtk_mmc_compatible mt2701_compat = {
@@ -438,6 +471,7 @@ static const struct mtk_mmc_compatible mt2701_compat = {
.stop_clk_fix = false,
.enhance_rx = false,
.support_64g = false,
.tune_resp_data_together = false,
};
static const struct mtk_mmc_compatible mt2712_compat = {
@@ -450,6 +484,7 @@ static const struct mtk_mmc_compatible mt2712_compat = {
.stop_clk_fix = true,
.enhance_rx = true,
.support_64g = true,
.tune_resp_data_together = true,
};
static const struct mtk_mmc_compatible mt7622_compat = {
@@ -462,6 +497,20 @@ static const struct mtk_mmc_compatible mt7622_compat = {
.stop_clk_fix = true,
.enhance_rx = true,
.support_64g = false,
.tune_resp_data_together = false,
};
static const struct mtk_mmc_compatible mt8183_compat = {
.clk_div_bits = 12,
.hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE0,
.async_fifo = true,
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
.enhance_rx = true,
.support_64g = true,
.tune_resp_data_together = true,
};
static const struct of_device_id msdc_of_ids[] = {
@@ -470,6 +519,7 @@ static const struct of_device_id msdc_of_ids[] = {
{ .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat},
{ .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat},
{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat},
{ .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat},
{}
};
MODULE_DEVICE_TABLE(of, msdc_of_ids);
@@ -774,11 +824,23 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
if (host->sclk <= 52000000) {
writel(host->def_tune_para.iocon, host->base + MSDC_IOCON);
writel(host->def_tune_para.pad_tune, host->base + tune_reg);
if (host->top_base != NULL) {
writel(host->def_tune_para.emmc_top_control,
host->top_base + EMMC_TOP_CONTROL);
writel(host->def_tune_para.emmc_top_cmd,
host->top_base + EMMC_TOP_CMD);
}
} else {
writel(host->saved_tune_para.iocon, host->base + MSDC_IOCON);
writel(host->saved_tune_para.pad_tune, host->base + tune_reg);
writel(host->saved_tune_para.pad_cmd_tune,
host->base + PAD_CMD_TUNE);
if (host->top_base != NULL) {
writel(host->saved_tune_para.emmc_top_control,
host->top_base + EMMC_TOP_CONTROL);
writel(host->saved_tune_para.emmc_top_cmd,
host->top_base + EMMC_TOP_CMD);
}
}
if (timing == MMC_TIMING_MMC_HS400 &&
@@ -1000,8 +1062,10 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
host->error |= REQ_CMD_TMO;
}
}
if (cmd->error)
dev_dbg(host->dev,
if (cmd->error &&
cmd->opcode != MMC_SEND_TUNING_BLOCK &&
cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
dev_info(host->dev,
"%s: cmd=%d arg=%08X; rsp %08X; cmd_error=%d\n",
__func__, cmd->opcode, cmd->arg, rsp[0],
cmd->error);
@@ -1190,11 +1254,14 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
data->error = -ETIMEDOUT;
else if (events & MSDC_INT_DATCRCERR)
data->error = -EILSEQ;
dev_dbg(host->dev, "%s: cmd=%d; blocks=%d",
__func__, mrq->cmd->opcode, data->blocks);
dev_dbg(host->dev, "data_error=%d xfer_size=%d\n",
(int)data->error, data->bytes_xfered);
if (mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK &&
mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) {
dev_info(host->dev, "%s: cmd=%d; blocks=%d",
__func__, mrq->cmd->opcode,
data->blocks);
dev_info(host->dev, "data_error=%d xfer_size=%d\n",
(int)data->error, data->bytes_xfered);
}
}
msdc_data_xfer_next(host, mrq, data);
@@ -1351,6 +1418,10 @@ static void msdc_init_hw(struct msdc_host *host)
writel(val, host->base + MSDC_INT);
writel(0, host->base + tune_reg);
if (host->top_base != NULL) {
writel(0, host->top_base + EMMC_TOP_CONTROL);
writel(0, host->top_base + EMMC_TOP_CMD);
}
writel(0, host->base + MSDC_IOCON);
sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0);
writel(0x403c0046, host->base + MSDC_PATCH_BIT);
@@ -1374,8 +1445,12 @@ static void msdc_init_hw(struct msdc_host *host)
sdr_set_field(host->base + MSDC_PATCH_BIT2,
MSDC_PB2_RESPWAIT, 3);
if (host->dev_comp->enhance_rx) {
sdr_set_bits(host->base + SDC_ADV_CFG0,
SDC_RX_ENHANCE_EN);
if (host->top_base != NULL)
sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
SDC_RX_ENH_EN);
else
sdr_set_bits(host->base + SDC_ADV_CFG0,
SDC_RX_ENHANCE_EN);
} else {
sdr_set_field(host->base + MSDC_PATCH_BIT2,
MSDC_PB2_RESPSTSENSEL, 2);
@@ -1393,11 +1468,26 @@ static void msdc_init_hw(struct msdc_host *host)
sdr_set_bits(host->base + MSDC_PATCH_BIT2,
MSDC_PB2_SUPPORT_64G);
if (host->dev_comp->data_tune) {
sdr_set_bits(host->base + tune_reg,
MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
if (host->top_base != NULL) {
sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY_SEL);
sdr_clr_bits(host->top_base + EMMC_TOP_CONTROL,
DATA_K_VALUE_SEL);
sdr_set_bits(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RD_RXDLY_SEL);
} else {
sdr_set_bits(host->base + tune_reg,
MSDC_PAD_TUNE_RD_SEL |
MSDC_PAD_TUNE_CMD_SEL);
}
} else {
/* choose clock tune */
sdr_set_bits(host->base + tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
if (host->top_base != NULL)
sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
PAD_RXDLY_SEL);
else
sdr_set_bits(host->base + tune_reg,
MSDC_PAD_TUNE_RXDLYSEL);
}
/* Configure to enable SDIO mode.
@@ -1415,6 +1505,16 @@ static void msdc_init_hw(struct msdc_host *host)
host->def_tune_para.pad_tune = readl(host->base + tune_reg);
host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON);
host->saved_tune_para.pad_tune = readl(host->base + tune_reg);
if (host->top_base != NULL) {
host->def_tune_para.emmc_top_control =
readl(host->top_base + EMMC_TOP_CONTROL);
host->def_tune_para.emmc_top_cmd =
readl(host->top_base + EMMC_TOP_CMD);
host->saved_tune_para.emmc_top_control =
readl(host->top_base + EMMC_TOP_CONTROL);
host->saved_tune_para.emmc_top_cmd =
readl(host->top_base + EMMC_TOP_CMD);
}
dev_dbg(host->dev, "init hardware done!");
}
@@ -1562,6 +1662,132 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
return delay_phase;
}
static int msdc_tune_resp_data(struct mmc_host *mmc, u32 opcode)
{
struct msdc_host *host = mmc_priv(mmc);
u32 rise_delay = 0, fall_delay = 0;
struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0,};
u8 final_delay, final_maxlen;
u32 tune_reg = host->dev_comp->pad_tune_reg;
int err;
int i, j;
sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_INT_DAT_LATCH_CK_SEL,
host->latch_ck);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
for (i = 0 ; i < PAD_DELAY_MAX; i++) {
if (host->top_base != NULL) {
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY, i);
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY, i);
} else {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
}
/*
* Using the same parameters, it may sometimes pass the test,
* but sometimes it may fail. To make sure the parameters are
* more stable, we test each set of parameters 3 times.
*/
for (j = 0; j < 3; j++) {
err = mmc_send_tuning(mmc, opcode, NULL);
if (!err) {
rise_delay |= (1 << i);
} else {
rise_delay &= ~(1 << i);
break;
}
}
}
final_rise_delay = get_best_delay(host, rise_delay);
/* if rising edge has enough margin, then do not scan falling edge */
if (final_rise_delay.maxlen >= 12 ||
(final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
goto skip_fall;
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
for (i = 0; i < PAD_DELAY_MAX; i++) {
if (host->top_base != NULL) {
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY, i);
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY, i);
} else {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
}
for (j = 0; j < 3; j++) {
err = mmc_send_tuning(mmc, opcode, NULL);
if (!err) {
fall_delay |= (1 << i);
} else {
fall_delay &= ~(1 << i);
break;
}
}
}
final_fall_delay = get_best_delay(host, fall_delay);
skip_fall:
final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
if (final_fall_delay.maxlen >= 12 && final_fall_delay.start < 4)
final_maxlen = final_fall_delay.maxlen;
if (final_maxlen == final_rise_delay.maxlen) {
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
if (host->top_base != NULL) {
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY,
final_rise_delay.final_phase);
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY,
final_rise_delay.final_phase);
} else {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY,
final_rise_delay.final_phase);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_rise_delay.final_phase);
}
final_delay = final_rise_delay.final_phase;
} else {
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
if (host->top_base != NULL) {
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY,
final_fall_delay.final_phase);
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY,
final_fall_delay.final_phase);
} else {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY,
final_fall_delay.final_phase);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_fall_delay.final_phase);
}
final_delay = final_fall_delay.final_phase;
}
dev_info(host->dev, "Final cmd/data pad delay: %x\n", final_delay);
return final_delay == 0xff ? -EIO : 0;
}
static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
{
struct msdc_host *host = mmc_priv(mmc);
@@ -1582,8 +1808,12 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
for (i = 0 ; i < PAD_DELAY_MAX; i++) {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY, i);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
/*
* Using the same parameters, it may sometimes pass the test,
* but sometimes it may fail. To make sure the parameters are
@@ -1607,8 +1837,12 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
for (i = 0; i < PAD_DELAY_MAX; i++) {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY, i);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY, i);
/*
* Using the same parameters, it may sometimes pass the test,
* but sometimes it may fail. To make sure the parameters are
@@ -1632,13 +1866,25 @@ skip_fall:
final_maxlen = final_fall_delay.maxlen;
if (final_maxlen == final_rise_delay.maxlen) {
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY,
final_rise_delay.final_phase);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY,
final_rise_delay.final_phase);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY,
final_rise_delay.final_phase);
final_delay = final_rise_delay.final_phase;
} else {
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY,
final_fall_delay.final_phase);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CMD,
PAD_CMD_RXDLY,
final_fall_delay.final_phase);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRDLY,
final_fall_delay.final_phase);
final_delay = final_fall_delay.final_phase;
}
if (host->dev_comp->async_fifo || host->hs200_cmd_int_delay)
@@ -1651,12 +1897,12 @@ skip_fall:
if (!cmd_err)
internal_delay |= (1 << i);
}
dev_dbg(host->dev, "Final internal delay: 0x%x\n", internal_delay);
dev_info(host->dev, "Final internal delay: 0x%x\n", internal_delay);
internal_delay_phase = get_best_delay(host, internal_delay);
sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRRDLY,
internal_delay_phase.final_phase);
skip_internal:
dev_dbg(host->dev, "Final cmd pad delay: %x\n", final_delay);
dev_info(host->dev, "Final cmd pad delay: %x\n", final_delay);
return final_delay == 0xff ? -EIO : 0;
}
@@ -1705,7 +1951,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)
final_cmd_delay.final_phase);
final_delay = final_cmd_delay.final_phase;
dev_dbg(host->dev, "Final cmd pad delay: %x\n", final_delay);
dev_info(host->dev, "Final cmd pad delay: %x\n", final_delay);
return final_delay == 0xff ? -EIO : 0;
}
@@ -1723,8 +1969,12 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
for (i = 0 ; i < PAD_DELAY_MAX; i++) {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY, i);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
ret = mmc_send_tuning(mmc, opcode, NULL);
if (!ret)
rise_delay |= (1 << i);
@@ -1738,8 +1988,12 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
for (i = 0; i < PAD_DELAY_MAX; i++) {
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY, i);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, i);
ret = mmc_send_tuning(mmc, opcode, NULL);
if (!ret)
fall_delay |= (1 << i);
@@ -1751,20 +2005,30 @@ skip_fall:
if (final_maxlen == final_rise_delay.maxlen) {
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_rise_delay.final_phase);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY,
final_rise_delay.final_phase);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_rise_delay.final_phase);
final_delay = final_rise_delay.final_phase;
} else {
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_fall_delay.final_phase);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY,
final_fall_delay.final_phase);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY,
final_fall_delay.final_phase);
final_delay = final_fall_delay.final_phase;
}
dev_dbg(host->dev, "Final data pad delay: %x\n", final_delay);
dev_info(host->dev, "Final data pad delay: %x\n", final_delay);
return final_delay == 0xff ? -EIO : 0;
}
@@ -1774,24 +2038,48 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
int ret;
u32 tune_reg = host->dev_comp->pad_tune_reg;
if (host->hs400_mode &&
host->dev_comp->hs400_tune)
ret = hs400_tune_response(mmc, opcode);
else
ret = msdc_tune_response(mmc, opcode);
if (ret == -EIO) {
dev_err(host->dev, "Tune response fail!\n");
return ret;
}
if (host->hs400_mode == false) {
ret = msdc_tune_data(mmc, opcode);
if (host->dev_comp->tune_resp_data_together) {
ret = msdc_tune_resp_data(mmc, opcode);
if (ret == -EIO)
dev_err(host->dev, "Tune data fail!\n");
dev_err(host->dev, "Tune cmd/data fail!\n");
if (host->hs400_mode) {
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
sdr_clr_bits(host->base + MSDC_IOCON,
MSDC_IOCON_W_DSPL);
if (host->top_base != NULL)
sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
PAD_DAT_RD_RXDLY, 0);
else
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_DATRRDLY, 0);
}
} else {
if (host->hs400_mode &&
host->dev_comp->hs400_tune)
ret = hs400_tune_response(mmc, opcode);
else
ret = msdc_tune_response(mmc, opcode);
if (ret == -EIO) {
dev_err(host->dev, "Tune response fail!\n");
return ret;
}
if (host->hs400_mode == false) {
ret = msdc_tune_data(mmc, opcode);
if (ret == -EIO)
dev_err(host->dev, "Tune data fail!\n");
}
}
host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON);
host->saved_tune_para.pad_tune = readl(host->base + tune_reg);
host->saved_tune_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE);
if (host->top_base != NULL) {
host->saved_tune_para.emmc_top_control = readl(host->top_base +
EMMC_TOP_CONTROL);
host->saved_tune_para.emmc_top_cmd = readl(host->top_base +
EMMC_TOP_CMD);
}
return ret;
}
@@ -1800,7 +2088,11 @@ static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
struct msdc_host *host = mmc_priv(mmc);
host->hs400_mode = true;
writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
if (host->top_base != NULL)
writel(host->hs400_ds_delay,
host->top_base + EMMC50_PAD_DS_TUNE);
else
writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
/* hs400 mode must set it to 0 */
sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS);
/* to improve read performance, set outstanding to 2 */
@@ -1887,6 +2179,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
goto host_free;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
host->top_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(host->top_base))
host->top_base = NULL;
ret = mmc_regulator_get_supply(mmc);
if (ret)
goto host_free;
@@ -2061,6 +2358,15 @@ static void msdc_save_reg(struct msdc_host *host)
host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0);
host->save_para.emmc50_cfg3 = readl(host->base + EMMC50_CFG3);
host->save_para.sdc_fifo_cfg = readl(host->base + SDC_FIFO_CFG);
if (host->top_base != NULL) {
host->save_para.emmc_top_control =
readl(host->top_base + EMMC_TOP_CONTROL);
host->save_para.emmc_top_cmd =
readl(host->top_base + EMMC_TOP_CMD);
host->save_para.emmc50_pad_ds_tune =
readl(host->top_base + EMMC50_PAD_DS_TUNE);
}
}
static void msdc_restore_reg(struct msdc_host *host)
@@ -2079,6 +2385,14 @@ static void msdc_restore_reg(struct msdc_host *host)
writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0);
writel(host->save_para.emmc50_cfg3, host->base + EMMC50_CFG3);
writel(host->save_para.sdc_fifo_cfg, host->base + SDC_FIFO_CFG);
if (host->top_base != NULL) {
writel(host->save_para.emmc_top_control,
host->top_base + EMMC_TOP_CONTROL);
writel(host->save_para.emmc_top_cmd,
host->top_base + EMMC_TOP_CMD);
writel(host->save_para.emmc50_pad_ds_tune,
host->top_base + EMMC50_PAD_DS_TUNE);
}
}
static int msdc_runtime_suspend(struct device *dev)

View File

@@ -53,6 +53,17 @@ config PINCTRL_MT6397
default MFD_MT6397
select PINCTRL_MTK
# For pintcrl command debug
config PINCTRL_MTK_DEBUG
bool "Mediatek pin control common debug"
depends on OF
default ARM64 && ARCH_MEDIATEK
select PINCTRL_MTK
help
Say yes here to enable support for MediaTek pinctrl debug command.
It can provide gpio status debug shell command.
We also can use these shell command to change gpio status.
endif
if !ARCH_MEDIATEK

View File

@@ -855,9 +855,11 @@ static int mtk_pmx_set_mode(struct pinctrl_dev *pctldev,
return mtk_pinctrl_set_gpio_mode(pctl, pin, mode);
#endif
if (pctl->devdata->spec_pinmux_set)
if (pctl->devdata->spec_pinmux_set) {
pctl->devdata->spec_pinmux_set(mtk_get_regmap(pctl, pin),
pin, mode);
return 0;
}
reg_addr = ((pin / MAX_GPIO_MODE_PER_REG) << pctl->devdata->port_shf)
+ pctl->devdata->pinmux_offset;

View File

@@ -559,6 +559,15 @@ config REGULATOR_MT6323
This driver supports the control of different power rails of device
through regulator interface.
config REGULATOR_MT6358
tristate "MediaTek MT6358 PMIC"
depends on MFD_MT6397
help
Say y here to select this option to enable the power regulator of
MediaTek MT6358 PMIC.
This driver supports the control of different power rails of device
through regulator interface.
config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP

View File

@@ -73,6 +73,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o

View File

@@ -0,0 +1,495 @@
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Hsin-Hsiung Wang <hsin-hsiung.wang@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/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6358/registers.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/mt6358-regulator.h>
#include <linux/regulator/of_regulator.h>
/*
* MT6358 regulators' information
*
* @desc: standard fields of regulator description.
* @qi: Mask for query enable signal status of regulators
*/
struct mt6358_regulator_info {
struct regulator_desc desc;
u32 status_reg;
u32 qi;
const u32 *index_table;
unsigned int n_table;
u32 vsel_shift;
};
#define MT6358_BUCK(match, vreg, min, max, step, \
volt_ranges, vosel_mask) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = (max - min)/step + 1, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = MT6358_BUCK_##vreg##_ELR0, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_BUCK_##vreg##_CON0, \
.enable_mask = BIT(0), \
}, \
.status_reg = MT6358_BUCK_##vreg##_DBG1, \
.qi = BIT(0), \
}
#define MT6358_LDO(match, vreg, ldo_volt_table, ldo_index_table, enreg, \
enbit, vosel, vosel_mask, vosel_shift) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_table_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.volt_table = ldo_volt_table, \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
}, \
.status_reg = MT6358_LDO_##vreg##_CON1, \
.qi = BIT(15), \
.index_table = ldo_index_table, \
.n_table = ARRAY_SIZE(ldo_index_table), \
.vsel_shift = vosel_shift, \
}
#define MT6358_LDO1(match, vreg, min, max, step, \
volt_ranges, vosel, vosel_mask) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = (max - min)/step + 1, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_LDO_##vreg##_CON0, \
.enable_mask = BIT(0), \
}, \
.status_reg = MT6358_LDO_##vreg##_DBG1, \
.qi = BIT(0), \
}
#define MT6358_REG_FIXED(match, vreg, enreg, enbit, volt) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = 1, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
.min_uV = volt, \
}, \
.status_reg = MT6358_LDO_##vreg##_CON1, \
.qi = BIT(15), \
}
static const struct regulator_linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500),
};
static const struct regulator_linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
static const struct regulator_linear_range buck_volt_range4[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500),
};
static const u32 vdram2_voltages[] = {
600000, 1800000,
};
static const u32 vsim1_voltages[] = {
1700000, 1800000, 2700000, 3000000, 3100000,
};
static const u32 vibr_voltages[] = {
1200000, 1300000, 1500000, 1800000,
2000000, 2800000, 3000000, 3300000,
};
static const u32 vusb_voltages[] = {
3000000, 3100000,
};
static const u32 vcamd_voltages[] = {
900000, 1000000, 1100000, 1200000,
1300000, 1500000, 1800000,
};
static const u32 vefuse_voltages[] = {
1700000, 1800000, 1900000,
};
static const u32 vmch_voltages[] = {
2900000, 3000000, 3300000,
};
static const u32 vcama1_voltages[] = {
1800000, 2500000, 2700000,
2800000, 2900000, 3000000,
};
static const u32 vemc_voltages[] = {
2900000, 3000000, 3300000,
};
static const u32 vcn33_bt_voltages[] = {
3300000, 3400000, 3500000,
};
static const u32 vcn33_wifi_voltages[] = {
3300000, 3400000, 3500000,
};
static const u32 vcama2_voltages[] = {
1800000, 2500000, 2700000,
2800000, 2900000, 3000000,
};
static const u32 vmc_voltages[] = {
1800000, 2900000, 3000000, 3300000,
};
static const u32 vldo28_voltages[] = {
2800000, 3000000,
};
static const u32 vsim2_voltages[] = {
1700000, 1800000, 2700000,
3000000, 3100000,
};
static const u32 vdram2_idx[] = {
0, 12,
};
static const u32 vsim1_idx[] = {
3, 4, 8, 11, 12,
};
static const u32 vibr_idx[] = {
0, 1, 2, 4, 5, 9, 11, 13,
};
static const u32 vusb_idx[] = {
3, 4,
};
static const u32 vcamd_idx[] = {
3, 4, 5, 6, 7, 9, 12,
};
static const u32 vefuse_idx[] = {
11, 12, 13,
};
static const u32 vmch_idx[] = {
2, 3, 5,
};
static const u32 vcama1_idx[] = {
0, 7, 9, 10, 11, 12,
};
static const u32 vemc_idx[] = {
2, 3, 5,
};
static const u32 vcn33_bt_idx[] = {
1, 2, 3,
};
static const u32 vcn33_wifi_idx[] = {
1, 2, 3,
};
static const u32 vcama2_idx[] = {
0, 7, 9, 10, 11, 12,
};
static const u32 vmc_idx[] = {
4, 10, 11, 13,
};
static const u32 vldo28_idx[] = {
1, 3,
};
static const u32 vsim2_idx[] = {
3, 4, 8, 11, 12,
};
static int mt6358_set_voltage_sel(
struct regulator_dev *rdev, unsigned int selector)
{
int idx, ret;
const u32 *pVoltidx;
struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
pVoltidx = (const u32 *)info->index_table;
idx = pVoltidx[selector];
ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg,
info->desc.vsel_mask, idx << info->vsel_shift);
return ret;
}
static int mt6358_get_voltage_sel(struct regulator_dev *rdev)
{
int idx, ret;
u32 selector;
struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
const u32 *pVoltidx;
ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector);
if (ret != 0) {
dev_info(&rdev->dev,
"Failed to get mt6358 %s vsel reg: %d\n",
info->desc.name, ret);
return ret;
}
selector = (selector & info->desc.vsel_mask) >> info->vsel_shift;
pVoltidx = (const u32 *)info->index_table;
ret = -1;
for (idx = 0; idx < info->desc.n_voltages; idx++) {
if (pVoltidx[idx] == selector) {
ret = idx;
break;
}
}
return ret;
}
static int mt6358_get_status(struct regulator_dev *rdev)
{
int ret;
u32 regval;
struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
ret = regmap_read(rdev->regmap, info->status_reg, &regval);
if (ret != 0) {
dev_info(&rdev->dev, "Failed to get enable reg: %d\n", ret);
return ret;
}
return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
}
static const struct regulator_ops mt6358_volt_range_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6358_get_status,
};
static const struct regulator_ops mt6358_volt_table_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
.set_voltage_sel = mt6358_set_voltage_sel,
.get_voltage_sel = mt6358_get_voltage_sel,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6358_get_status,
};
static const struct regulator_ops mt6358_volt_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6358_get_status,
};
/* The array is indexed by id(MT6358_ID_XXX) */
static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
buck_volt_range2, 0x7f),
MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
buck_volt_range1, 0x7f),
MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
buck_volt_range3, 0x3f),
MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
buck_volt_range1, 0x7f),
MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
buck_volt_range1, 0x7f),
MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
buck_volt_range1, 0x7f),
MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
buck_volt_range2, 0x7f),
MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
buck_volt_range1, 0x7f),
MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
buck_volt_range4, 0x7f),
MT6358_REG_FIXED("ldo_vrf12", VRF12,
MT6358_LDO_VRF12_CON0, 0, 1200000),
MT6358_REG_FIXED("ldo_vio18", VIO18,
MT6358_LDO_VIO18_CON0, 0, 1800000),
MT6358_REG_FIXED("ldo_vcamio", VCAMIO,
MT6358_LDO_VCAMIO_CON0, 0, 1800000),
MT6358_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000),
MT6358_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000),
MT6358_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000),
MT6358_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000),
MT6358_REG_FIXED("ldo_vaux18", VAUX18,
MT6358_LDO_VAUX18_CON0, 0, 1800000),
MT6358_REG_FIXED("ldo_vbif28", VBIF28,
MT6358_LDO_VBIF28_CON0, 0, 2800000),
MT6358_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000),
MT6358_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000),
MT6358_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000),
MT6358_REG_FIXED("ldo_vaud28", VAUD28,
MT6358_LDO_VAUD28_CON0, 0, 2800000),
MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0),
MT6358_LDO("ldo_vsim1", VSIM1, vsim1_voltages, vsim1_idx,
MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx,
MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700, 8),
MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx,
MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx,
MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vmch", VMCH, vmch_voltages, vmch_idx,
MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700, 8),
MT6358_LDO("ldo_vcama1", VCAMA1, vcama1_voltages, vcama1_idx,
MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vemc", VEMC, vemc_voltages, vemc_idx,
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700, 8),
MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_voltages, vcn33_bt_idx,
MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300, 8),
MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_wifi_voltages,
vcn33_wifi_idx, MT6358_LDO_VCN33_CON0_1,
0, MT6358_VCN33_ANA_CON0, 0x300, 8),
MT6358_LDO("ldo_vcama2", VCAMA2, vcama2_voltages, vcama2_idx,
MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00, 8),
MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx,
MT6358_LDO_VLDO28_CON0_0, 0, MT6358_VLDO28_ANA_CON0, 0x300, 8),
MT6358_LDO("ldo_vsim2", VSIM2, vsim2_voltages, vsim2_idx,
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00, 8),
MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_CON0, 0x7f),
MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_CON2, 0x7f),
MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_CON3, 0x7f),
MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_CON1, 0x7f),
};
static int mt6358_regulator_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
int i;
u32 reg_value;
/* Read PMIC chip revision to update constraints and voltage table */
if (regmap_read(mt6397->regmap, MT6358_SWCID, &reg_value) < 0) {
dev_err(&pdev->dev, "Failed to read Chip ID\n");
return -EIO;
}
for (i = 0; i < MT6358_MAX_REGULATOR; i++) {
config.dev = &pdev->dev;
config.driver_data = &mt6358_regulators[i];
config.regmap = mt6397->regmap;
rdev = devm_regulator_register(&pdev->dev,
&mt6358_regulators[i].desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n",
mt6358_regulators[i].desc.name);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct platform_device_id mt6358_platform_ids[] = {
{"mt6358-regulator", 0},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(platform, mt6358_platform_ids);
static const struct of_device_id mt6358_of_match[] = {
{ .compatible = "mediatek,mt6358-regulator", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mt6358_of_match);
static struct platform_driver mt6358_regulator_driver = {
.driver = {
.name = "mt6358-regulator",
.of_match_table = of_match_ptr(mt6358_of_match),
},
.probe = mt6358_regulator_probe,
.id_table = mt6358_platform_ids,
};
module_platform_driver(mt6358_regulator_driver);
MODULE_AUTHOR("Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>");
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6358 PMIC");
MODULE_LICENSE("GPL");

View File

@@ -322,10 +322,9 @@ static int mtk_rtc_probe(struct platform_device *pdev)
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->irq = platform_get_irq(pdev, 0);
if (rtc->irq < 0)
return rtc->irq;
rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev;

View File

@@ -10,6 +10,18 @@ config MTK_INFRACFG
INFRACFG controller contains various infrastructure registers not
directly associated to any device.
config MTK_CMDQ
tristate "MediaTek CMDQ Support"
depends on ARCH_MEDIATEK || COMPILE_TEST
select MAILBOX
select MTK_CMDQ_MBOX
select MTK_INFRACFG
help
Say yes here to add support for the MediaTek Command Queue (CMDQ)
driver. The CMDQ is used to help read/write registers with critical
time limitation, such as updating display configuration during the
vblank.
config MTK_PMIC_WRAP
tristate "MediaTek PMIC Wrapper Support"
select REGMAP

View File

@@ -1,3 +1,4 @@
obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o

View File

@@ -24,6 +24,7 @@
#include <dt-bindings/power/mt6797-power.h>
#include <dt-bindings/power/mt7622-power.h>
#include <dt-bindings/power/mt8173-power.h>
#include <dt-bindings/power/mt8183-power.h>
#define SPM_VDE_PWR_CON 0x0210
#define SPM_MFG_PWR_CON 0x0214
@@ -84,6 +85,13 @@ enum clk_id {
CLK_ETHIF,
CLK_VDEC,
CLK_HIFSEL,
CLK_ISP,
CLK_AUDIO,
CLK_CAM,
CLK_VPU,
CLK_VPU1,
CLK_VPU2,
CLK_VPU3,
CLK_MAX,
};
@@ -96,6 +104,13 @@ static const char * const clk_names[] = {
"ethif",
"vdec",
"hif_sel",
"isp",
"audio",
"cam",
"vpu",
"vpu1",
"vpu2",
"vpu3",
NULL,
};
@@ -810,6 +825,147 @@ static const struct scp_subdomain scp_subdomain_mt8173[] = {
{MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
};
/*
* MT8183 power domain support
*/
static const struct scp_domain_data scp_domain_data_mt8183[] = {
[MT8183_POWER_DOMAIN_AUDIO] = {
.name = "audio",
.sta_mask = PWR_STATUS_AUDIO,
.ctl_offs = 0x0314,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_AUDIO},
},
[MT8183_POWER_DOMAIN_CONN] = {
.name = "conn",
.sta_mask = PWR_STATUS_CONN,
.ctl_offs = 0x032c,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_MFG_ASYNC] = {
.name = "mfg_async",
.sta_mask = PWR_STATUS_MFG_ASYNC,
.ctl_offs = 0x0334,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.clk_id = {CLK_MFG},
},
[MT8183_POWER_DOMAIN_MFG] = {
.name = "mfg",
.sta_mask = PWR_STATUS_MFG,
.ctl_offs = 0x0338,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_MFG_CORE0] = {
.name = "mfg_core0",
.sta_mask = BIT(7),
.ctl_offs = 0x034c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_MFG_CORE1] = {
.name = "mfg_core1",
.sta_mask = BIT(20),
.ctl_offs = 0x0310,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
.sta_mask = PWR_STATUS_MFG_2D,
.ctl_offs = 0x0348,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_DISP] = {
.name = "disp",
.sta_mask = PWR_STATUS_DISP,
.ctl_offs = 0x030c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_MM},
},
[MT8183_POWER_DOMAIN_CAM] = {
.name = "cam",
.sta_mask = BIT(25),
.ctl_offs = 0x0344,
.sram_pdn_bits = GENMASK(9, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_CAM},
},
[MT8183_POWER_DOMAIN_ISP] = {
.name = "isp",
.sta_mask = PWR_STATUS_ISP,
.ctl_offs = 0x0308,
.sram_pdn_bits = GENMASK(9, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_ISP},
},
[MT8183_POWER_DOMAIN_VDEC] = {
.name = "vdec",
.sta_mask = BIT(31),
.ctl_offs = 0x0300,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_VENC] = {
.name = "venc",
.sta_mask = PWR_STATUS_VENC,
.ctl_offs = 0x0304,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_NONE},
},
[MT8183_POWER_DOMAIN_VPU_TOP] = {
.name = "vpu_top",
.sta_mask = BIT(26),
.ctl_offs = 0x0324,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_VPU, CLK_VPU1},
},
[MT8183_POWER_DOMAIN_VPU_CORE0] = {
.name = "vpu_core0",
.sta_mask = BIT(27),
.ctl_offs = 0x33c,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_VPU2},
},
[MT8183_POWER_DOMAIN_VPU_CORE1] = {
.name = "vpu_core1",
.sta_mask = BIT(28),
.ctl_offs = 0x0340,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_VPU3},
},
};
static const struct scp_subdomain scp_subdomain_mt8183[] = {
{MT8183_POWER_DOMAIN_MFG_ASYNC, MT8183_POWER_DOMAIN_MFG},
{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_2D},
{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_CORE0},
{MT8183_POWER_DOMAIN_MFG, MT8183_POWER_DOMAIN_MFG_CORE1},
{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_CAM},
{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_ISP},
{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VDEC},
{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VENC},
{MT8183_POWER_DOMAIN_DISP, MT8183_POWER_DOMAIN_VPU_TOP},
{MT8183_POWER_DOMAIN_VPU_TOP, MT8183_POWER_DOMAIN_VPU_CORE0},
{MT8183_POWER_DOMAIN_VPU_TOP, MT8183_POWER_DOMAIN_VPU_CORE1},
};
static const struct scp_soc_data mt2701_data = {
.domains = scp_domain_data_mt2701,
.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
@@ -850,6 +1006,17 @@ static const struct scp_soc_data mt8173_data = {
}
};
static const struct scp_soc_data mt8183_data = {
.domains = scp_domain_data_mt8183,
.num_domains = ARRAY_SIZE(scp_domain_data_mt8183),
.subdomains = scp_subdomain_mt8183,
.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8183),
.regs = {
.pwr_sta_offs = 0x0180,
.pwr_sta2nd_offs = 0x0184
}
};
/*
* scpsys driver init
*/
@@ -867,6 +1034,9 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
}, {
.compatible = "mediatek,mt8173-scpsys",
.data = &mt8173_data,
}, {
.compatible = "mediatek,mt8183-scpsys",
.data = &mt8183_data,
}, {
/* sentinel */
}
@@ -874,15 +1044,13 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
static int scpsys_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct scp_subdomain *sd;
const struct scp_soc_data *soc;
struct scp *scp;
struct genpd_onecell_data *pd_data;
int i, ret;
match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
soc = (const struct scp_soc_data *)match->data;
soc = of_device_get_match_data(&pdev->dev);
scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs);
if (IS_ERR(scp))

View File

@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Houlong Wei <houlong.wei@mediatek.com>
*
*/
#ifndef _DT_BINDINGS_GCE_MT8173_H
#define _DT_BINDINGS_GCE_MT8173_H
#define CMDQ_NO_TIMEOUT 0xffffffff
#define CMDQ_THR_MAX_COUNT 16
/* GCE HW thread priority */
#define CMDQ_THR_PRIO_LOWEST 0
#define CMDQ_THR_PRIO_HIGHEST 1
/* GCE SUBSYS */
#define SUBSYS_1400XXXX 1
#define SUBSYS_1401XXXX 2
#define SUBSYS_1402XXXX 3
/* GCE HW EVENT */
#define CMDQ_EVENT_DISP_OVL0_SOF 11
#define CMDQ_EVENT_DISP_OVL1_SOF 12
#define CMDQ_EVENT_DISP_RDMA0_SOF 13
#define CMDQ_EVENT_DISP_RDMA1_SOF 14
#define CMDQ_EVENT_DISP_RDMA2_SOF 15
#define CMDQ_EVENT_DISP_WDMA0_SOF 16
#define CMDQ_EVENT_DISP_WDMA1_SOF 17
#define CMDQ_EVENT_DISP_OVL0_EOF 39
#define CMDQ_EVENT_DISP_OVL1_EOF 40
#define CMDQ_EVENT_DISP_RDMA0_EOF 41
#define CMDQ_EVENT_DISP_RDMA1_EOF 42
#define CMDQ_EVENT_DISP_RDMA2_EOF 43
#define CMDQ_EVENT_DISP_WDMA0_EOF 44
#define CMDQ_EVENT_DISP_WDMA1_EOF 45
#define CMDQ_EVENT_MUTEX0_STREAM_EOF 53
#define CMDQ_EVENT_MUTEX1_STREAM_EOF 54
#define CMDQ_EVENT_MUTEX2_STREAM_EOF 55
#define CMDQ_EVENT_MUTEX3_STREAM_EOF 56
#define CMDQ_EVENT_MUTEX4_STREAM_EOF 57
#define CMDQ_EVENT_DISP_RDMA0_UNDERRUN 63
#define CMDQ_EVENT_DISP_RDMA1_UNDERRUN 64
#define CMDQ_EVENT_DISP_RDMA2_UNDERRUN 65
#endif

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
#define _DT_BINDINGS_POWER_MT8183_POWER_H
#ifndef _DT_BINDINGS_POWER_MT8173_POWER_H
#define _DT_BINDINGS_POWER_MT8173_POWER_H
#define MT8173_POWER_DOMAIN_VDEC 0
#define MT8173_POWER_DOMAIN_VENC 1
@@ -13,4 +13,4 @@
#define MT8173_POWER_DOMAIN_MFG_2D 8
#define MT8173_POWER_DOMAIN_MFG 9
#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */
#endif /* _DT_BINDINGS_POWER_MT8173_POWER_H */

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2018 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 http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
#define _DT_BINDINGS_POWER_MT8183_POWER_H
#define MT8183_POWER_DOMAIN_AUDIO 0
#define MT8183_POWER_DOMAIN_CONN 1
#define MT8183_POWER_DOMAIN_MFG_ASYNC 2
#define MT8183_POWER_DOMAIN_MFG 3
#define MT8183_POWER_DOMAIN_MFG_CORE0 4
#define MT8183_POWER_DOMAIN_MFG_CORE1 5
#define MT8183_POWER_DOMAIN_MFG_2D 6
#define MT8183_POWER_DOMAIN_DISP 7
#define MT8183_POWER_DOMAIN_CAM 8
#define MT8183_POWER_DOMAIN_ISP 9
#define MT8183_POWER_DOMAIN_VDEC 10
#define MT8183_POWER_DOMAIN_VENC 11
#define MT8183_POWER_DOMAIN_VPU_TOP 12
#define MT8183_POWER_DOMAIN_VPU_CORE0 13
#define MT8183_POWER_DOMAIN_VPU_CORE1 14
#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Hsin-Hsiung Wang <hsin-hsiung.wang@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 __LINUX_REGULATOR_MT6358_H
#define __LINUX_REGULATOR_MT6358_H
enum {
MT6358_ID_VDRAM1 = 0,
MT6358_ID_VCORE,
MT6358_ID_VPA,
MT6358_ID_VPROC11,
MT6358_ID_VPROC12,
MT6358_ID_VGPU,
MT6358_ID_VS2,
MT6358_ID_VMODEM,
MT6358_ID_VS1,
MT6358_ID_VDRAM2 = 9,
MT6358_ID_VSIM1,
MT6358_ID_VIBR,
MT6358_ID_VRF12,
MT6358_ID_VIO18,
MT6358_ID_VUSB,
MT6358_ID_VCAMIO,
MT6358_ID_VCAMD,
MT6358_ID_VCN18,
MT6358_ID_VFE28,
MT6358_ID_VSRAM_PROC11,
MT6358_ID_VCN28,
MT6358_ID_VSRAM_OTHERS,
MT6358_ID_VSRAM_GPU,
MT6358_ID_VXO22,
MT6358_ID_VEFUSE,
MT6358_ID_VAUX18,
MT6358_ID_VMCH,
MT6358_ID_VBIF28,
MT6358_ID_VSRAM_PROC12,
MT6358_ID_VCAMA1,
MT6358_ID_VEMC,
MT6358_ID_VIO28,
MT6358_ID_VA12,
MT6358_ID_VRF18,
MT6358_ID_VCN33_BT,
MT6358_ID_VCN33_WIFI,
MT6358_ID_VCAMA2,
MT6358_ID_VMC,
MT6358_ID_VLDO28,
MT6358_ID_VAUD28,
MT6358_ID_VSIM2,
MT6358_ID_RG_MAX,
};
#define MT6358_MAX_REGULATOR MT6358_ID_RG_MAX
#endif /* __LINUX_REGULATOR_MT6358_H */