Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

Add REF2USB_TX clock support into MT8173 APMIXEDSYS. This clock
is needed by USB 3.0.

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>

+161 -8
+1 -1
drivers/clk/mediatek/Makefile
··· 1 - obj-y += clk-mtk.o clk-pll.o clk-gate.o 1 + obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o 2 2 obj-$(CONFIG_RESET_CONTROLLER) += reset.o 3 3 obj-y += clk-mt8135.o 4 4 obj-y += clk-mt8173.o
+107
drivers/clk/mediatek/clk-apmixed.c
··· 1 + /* 2 + * Copyright (c) 2015 MediaTek Inc. 3 + * Author: James Liao <jamesjj.liao@mediatek.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/delay.h> 16 + #include <linux/of_address.h> 17 + #include <linux/slab.h> 18 + 19 + #include "clk-mtk.h" 20 + 21 + #define REF2USB_TX_EN BIT(0) 22 + #define REF2USB_TX_LPF_EN BIT(1) 23 + #define REF2USB_TX_OUT_EN BIT(2) 24 + #define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \ 25 + REF2USB_TX_OUT_EN) 26 + 27 + struct mtk_ref2usb_tx { 28 + struct clk_hw hw; 29 + void __iomem *base_addr; 30 + }; 31 + 32 + static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw) 33 + { 34 + return container_of(hw, struct mtk_ref2usb_tx, hw); 35 + } 36 + 37 + static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw) 38 + { 39 + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); 40 + 41 + return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK; 42 + } 43 + 44 + static int mtk_ref2usb_tx_prepare(struct clk_hw *hw) 45 + { 46 + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); 47 + u32 val; 48 + 49 + val = readl(tx->base_addr); 50 + 51 + val |= REF2USB_TX_EN; 52 + writel(val, tx->base_addr); 53 + udelay(100); 54 + 55 + val |= REF2USB_TX_LPF_EN; 56 + writel(val, tx->base_addr); 57 + 58 + val |= REF2USB_TX_OUT_EN; 59 + writel(val, tx->base_addr); 60 + 61 + return 0; 62 + } 63 + 64 + static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw) 65 + { 66 + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); 67 + u32 val; 68 + 69 + val = readl(tx->base_addr); 70 + val &= ~REF2USB_EN_MASK; 71 + writel(val, tx->base_addr); 72 + } 73 + 74 + static const struct clk_ops mtk_ref2usb_tx_ops = { 75 + .is_prepared = mtk_ref2usb_tx_is_prepared, 76 + .prepare = mtk_ref2usb_tx_prepare, 77 + .unprepare = mtk_ref2usb_tx_unprepare, 78 + }; 79 + 80 + struct clk * __init mtk_clk_register_ref2usb_tx(const char *name, 81 + const char *parent_name, void __iomem *reg) 82 + { 83 + struct mtk_ref2usb_tx *tx; 84 + struct clk_init_data init = {}; 85 + struct clk *clk; 86 + 87 + tx = kzalloc(sizeof(*tx), GFP_KERNEL); 88 + if (!tx) 89 + return ERR_PTR(-ENOMEM); 90 + 91 + tx->base_addr = reg; 92 + tx->hw.init = &init; 93 + 94 + init.name = name; 95 + init.ops = &mtk_ref2usb_tx_ops; 96 + init.parent_names = &parent_name; 97 + init.num_parents = 1; 98 + 99 + clk = clk_register(NULL, &tx->hw); 100 + 101 + if (IS_ERR(clk)) { 102 + pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk)); 103 + kfree(tx); 104 + } 105 + 106 + return clk; 107 + }
+47
drivers/clk/mediatek/clk-mt8173.c
··· 982 982 } 983 983 CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init); 984 984 985 + struct mtk_clk_usb { 986 + int id; 987 + const char *name; 988 + const char *parent; 989 + u32 reg_ofs; 990 + }; 991 + 992 + #define APMIXED_USB(_id, _name, _parent, _reg_ofs) { \ 993 + .id = _id, \ 994 + .name = _name, \ 995 + .parent = _parent, \ 996 + .reg_ofs = _reg_ofs, \ 997 + } 998 + 999 + static const struct mtk_clk_usb apmixed_usb[] __initconst = { 1000 + APMIXED_USB(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8), 1001 + }; 1002 + 985 1003 #define MT8173_PLL_FMAX (3000UL * MHZ) 986 1004 987 1005 #define CON0_MT8173_RST_BAR BIT(24) ··· 1060 1042 static void __init mtk_apmixedsys_init(struct device_node *node) 1061 1043 { 1062 1044 struct clk_onecell_data *clk_data; 1045 + void __iomem *base; 1046 + struct clk *clk; 1047 + int r, i; 1048 + 1049 + base = of_iomap(node, 0); 1050 + if (!base) { 1051 + pr_err("%s(): ioremap failed\n", __func__); 1052 + return; 1053 + } 1063 1054 1064 1055 mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); 1065 1056 if (!clk_data) 1066 1057 return; 1067 1058 1068 1059 mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); 1060 + 1061 + for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) { 1062 + const struct mtk_clk_usb *cku = &apmixed_usb[i]; 1063 + 1064 + clk = mtk_clk_register_ref2usb_tx(cku->name, cku->parent, 1065 + base + cku->reg_ofs); 1066 + 1067 + if (IS_ERR(clk)) { 1068 + pr_err("Failed to register clk %s: %ld\n", cku->name, 1069 + PTR_ERR(clk)); 1070 + continue; 1071 + } 1072 + 1073 + clk_data->clks[cku->id] = clk; 1074 + } 1075 + 1076 + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 1077 + if (r) 1078 + pr_err("%s(): could not register clock provider: %d\n", 1079 + __func__, r); 1069 1080 1070 1081 mtk_clk_enable_critical(); 1071 1082 }
+3
drivers/clk/mediatek/clk-mtk.h
··· 180 180 const struct mtk_pll_data *plls, int num_plls, 181 181 struct clk_onecell_data *clk_data); 182 182 183 + struct clk *mtk_clk_register_ref2usb_tx(const char *name, 184 + const char *parent_name, void __iomem *reg); 185 + 183 186 #ifdef CONFIG_RESET_CONTROLLER 184 187 void mtk_register_reset_controller(struct device_node *np, 185 188 unsigned int num_regs, int regofs);
+1 -6
drivers/clk/mediatek/clk-pll.c
··· 317 317 const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data) 318 318 { 319 319 void __iomem *base; 320 - int r, i; 320 + int i; 321 321 struct clk *clk; 322 322 323 323 base = of_iomap(node, 0); ··· 339 339 340 340 clk_data->clks[pll->id] = clk; 341 341 } 342 - 343 - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 344 - if (r) 345 - pr_err("%s(): could not register clock provider: %d\n", 346 - __func__, r); 347 342 }
+2 -1
include/dt-bindings/clock/mt8173-clk.h
··· 175 175 #define CLK_APMIXED_APLL2 12 176 176 #define CLK_APMIXED_LVDSPLL 13 177 177 #define CLK_APMIXED_MSDCPLL2 14 178 - #define CLK_APMIXED_NR_CLK 15 178 + #define CLK_APMIXED_REF2USB_TX 15 179 + #define CLK_APMIXED_NR_CLK 16 179 180 180 181 /* INFRA_SYS */ 181 182