From c2681ce7d99d8185e43b8df4e148375268250bad Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Thu, 2 Sep 2021 16:09:08 +0300 Subject: [PATCH] MSM8916Pkg: Implement clocks Signed-off-by: Ivaylo Ivanov Cc: Bingxing Wang (nice email) --- MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf | 35 + MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf | 26 + MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf | 28 + MSM8916Pkg/Drivers/ClockDxe/Driver.c | 22 + MSM8916Pkg/Drivers/ClockDxe/LibraryBS.c | 20 + MSM8916Pkg/Drivers/ClockDxe/LibraryImpl.c | 33 + MSM8916Pkg/Drivers/ClockDxe/Source.txt | 3 + MSM8916Pkg/Drivers/ClockDxe/clock-local.c | 387 +++++++++++ MSM8916Pkg/Drivers/ClockDxe/clock.c | 193 ++++++ MSM8916Pkg/Drivers/ClockDxe/clock_lib2.c | 277 ++++++++ MSM8916Pkg/Drivers/ClockDxe/clock_p.h | 110 ++++ MSM8916Pkg/Drivers/ClockDxe/clock_pll.c | 139 ++++ MSM8916Pkg/Include/Chipset/clock-local.h | 235 +++++++ MSM8916Pkg/Include/Chipset/clock.h | 81 +++ MSM8916Pkg/Include/Chipset/clock_lib2.h | 223 +++++++ MSM8916Pkg/Include/Chipset/clock_pll.h | 102 +++ MSM8916Pkg/Include/Library/LKEnvLib.h | 111 ++++ MSM8916Pkg/Include/Library/QcomClockLib.h | 12 + .../Library/QcomPlatformClockInitLib.h | 11 + MSM8916Pkg/Include/Library/minstdbool.h | 11 + MSM8916Pkg/Include/Library/minstdint.h | 70 ++ MSM8916Pkg/Include/Library/minstring.h | 17 + MSM8916Pkg/Include/Platform/clock.h | 93 +++ MSM8916Pkg/Include/Platform/iomap.h | 286 ++++++++ MSM8916Pkg/Include/Platform/irqs.h | 68 ++ MSM8916Pkg/Include/Protocol/QcomClock.h | 41 ++ .../QcomPlatformClockInitLib.inf | 24 + .../QcomPlatformClockInitLib/msm8916-clock.c | 612 ++++++++++++++++++ MSM8916Pkg/MSM8916Pkg.dec | 1 + MSM8916Pkg/MSM8916Pkg.dsc | 23 +- MSM8916Pkg/MSM8916Pkg.fdf | 4 + 31 files changed, 3297 insertions(+), 1 deletion(-) create mode 100644 MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf create mode 100644 MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf create mode 100644 MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf create mode 100644 MSM8916Pkg/Drivers/ClockDxe/Driver.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/LibraryBS.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/LibraryImpl.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/Source.txt create mode 100644 MSM8916Pkg/Drivers/ClockDxe/clock-local.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/clock.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/clock_lib2.c create mode 100644 MSM8916Pkg/Drivers/ClockDxe/clock_p.h create mode 100644 MSM8916Pkg/Drivers/ClockDxe/clock_pll.c create mode 100644 MSM8916Pkg/Include/Chipset/clock-local.h create mode 100644 MSM8916Pkg/Include/Chipset/clock.h create mode 100644 MSM8916Pkg/Include/Chipset/clock_lib2.h create mode 100644 MSM8916Pkg/Include/Chipset/clock_pll.h create mode 100644 MSM8916Pkg/Include/Library/LKEnvLib.h create mode 100644 MSM8916Pkg/Include/Library/QcomClockLib.h create mode 100644 MSM8916Pkg/Include/Library/QcomPlatformClockInitLib.h create mode 100644 MSM8916Pkg/Include/Library/minstdbool.h create mode 100644 MSM8916Pkg/Include/Library/minstdint.h create mode 100644 MSM8916Pkg/Include/Library/minstring.h create mode 100644 MSM8916Pkg/Include/Platform/clock.h create mode 100644 MSM8916Pkg/Include/Platform/iomap.h create mode 100644 MSM8916Pkg/Include/Platform/irqs.h create mode 100644 MSM8916Pkg/Include/Protocol/QcomClock.h create mode 100644 MSM8916Pkg/Library/QcomPlatformClockInitLib/QcomPlatformClockInitLib.inf create mode 100644 MSM8916Pkg/Library/QcomPlatformClockInitLib/msm8916-clock.c diff --git a/MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf b/MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf new file mode 100644 index 0000000..437b66e --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf @@ -0,0 +1,35 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ClockDxe + FILE_GUID = 3EBA1869-45CA-41E1-AD6B-40BA8012A538 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = ClockDxeInitialize + +[Sources.common] + Driver.c + LibraryImpl.c + clock.c + clock_lib2.c + clock-local.c + clock_pll.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + MSM8916Pkg/MSM8916Pkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + QcomPlatformClockInitLib + TimerLib + +[BuildOptions.AARCH64] + GCC:*_*_*_CC_FLAGS = -Wno-pointer-to-int-cast -Wno-overflow + +[Protocols] + gQcomClockProtocolGuid + +[Depex] + TRUE diff --git a/MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf b/MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf new file mode 100644 index 0000000..b7013a8 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf @@ -0,0 +1,26 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ClockImplLib + FILE_GUID = 44790987-E75E-4178-AE98-AC961D33D8FE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ClockLib + CONSTRUCTOR = ClockImplLibInitialize + +[Sources.common] + LibraryImpl.c + clock.c + clock_lib2.c + clock-local.c + clock_pll.c + +[BuildOptions.AARCH64] + GCC:*_*_*_CC_FLAGS = -Wno-pointer-to-int-cast -Wno-overflow + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + MSM8916Pkg/MSM8916Pkg.dec + +[LibraryClasses] + QcomPlatformClockInitLib diff --git a/MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf b/MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf new file mode 100644 index 0000000..4ec2c66 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf @@ -0,0 +1,28 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ClockLib + FILE_GUID = 84B9E8B0-E69E-451A-8520-0BDBFDCE2364 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ClockLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ClockLibConstructor + +[Sources.common] + LibraryBS.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + MSM8916Pkg/MSM8916Pkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + +[BuildOptions.AARCH64] + GCC:*_*_*_CC_FLAGS = -Wno-pointer-to-int-cast -Wno-overflow + +[Protocols] + gQcomClockProtocolGuid + +[Depex] + gQcomClockProtocolGuid diff --git a/MSM8916Pkg/Drivers/ClockDxe/Driver.c b/MSM8916Pkg/Drivers/ClockDxe/Driver.c new file mode 100644 index 0000000..615bd41 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/Driver.c @@ -0,0 +1,22 @@ +#include + +#include + +#include +#include + +EFI_STATUS +EFIAPI +ClockDxeInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + ClockImplLibInitialize(); + + Status = gBS->InstallMultipleProtocolInterfaces( + &Handle, &gQcomClockProtocolGuid, gClock, NULL); + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/MSM8916Pkg/Drivers/ClockDxe/LibraryBS.c b/MSM8916Pkg/Drivers/ClockDxe/LibraryBS.c new file mode 100644 index 0000000..2ee7484 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/LibraryBS.c @@ -0,0 +1,20 @@ +#include + +#include + +#include +#include + +QCOM_CLOCK_PROTOCOL *gClock = NULL; + +RETURN_STATUS +EFIAPI +ClockLibConstructor(VOID) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gQcomClockProtocolGuid, NULL, (VOID **)&gClock); + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/MSM8916Pkg/Drivers/ClockDxe/LibraryImpl.c b/MSM8916Pkg/Drivers/ClockDxe/LibraryImpl.c new file mode 100644 index 0000000..3b2d7f3 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/LibraryImpl.c @@ -0,0 +1,33 @@ +#include + +#include + +#include +#include + +#include "clock_p.h" + +QCOM_CLOCK_PROTOCOL *gClock = NULL; + +STATIC QCOM_CLOCK_PROTOCOL mInternalClock = { + clk_get, clk_enable, clk_disable, + clk_get_rate, clk_set_rate, clk_set_parent, + clk_get_parent, clk_get_set_enable, clk_reset, +}; + +RETURN_STATUS +EFIAPI +ClockImplLibInitialize(VOID) +{ + EFI_STATUS Status; + struct clk_lookup *clist = NULL; + unsigned num = 0; + + gClock = &mInternalClock; + + Status = LibQcomPlatformClockInit(&clist, &num); + ASSERT_EFI_ERROR(Status); + clk_init(clist, num); + + return Status; +} diff --git a/MSM8916Pkg/Drivers/ClockDxe/Source.txt b/MSM8916Pkg/Drivers/ClockDxe/Source.txt new file mode 100644 index 0000000..52e1d56 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/Source.txt @@ -0,0 +1,3 @@ +URL: https://source.codeaurora.org/quic/la/kernel/lk +BRANCH: LA.AF.1.1-02810-8064.0 +UPDATED FROM: LA.BF64.1.2.3-01510-8x94.0 diff --git a/MSM8916Pkg/Drivers/ClockDxe/clock-local.c b/MSM8916Pkg/Drivers/ClockDxe/clock-local.c new file mode 100644 index 0000000..01eb0ec --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/clock-local.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +// Must come in order +#include + +#include "clock_p.h" + +/* + * When enabling/disabling a clock, check the halt bit up to this number + * number of times (with a 1 us delay in between) before continuing. + */ +#define HALT_CHECK_MAX_LOOPS 100 +/* For clock without halt checking, wait this long after enables/disables. */ +#define HALT_CHECK_DELAY_US 10 + +struct clk_freq_tbl local_dummy_freq = F_END; + +/* + * Clock enable/disable functions + */ +static int branch_clk_is_halted(const struct branch *clk) +{ + int invert = (clk->halt_check == ENABLE); + int status_bit = readl_relaxed(clk->halt_reg) & BIT(clk->halt_bit); + return invert ? !status_bit : status_bit; +} + +static void __branch_clk_enable_reg(const struct branch *clk, const char *name) +{ + uint32_t reg_val; + + if (clk->en_mask) { + reg_val = readl_relaxed(clk->ctl_reg); + reg_val |= clk->en_mask; + writel_relaxed(reg_val, clk->ctl_reg); + } + + /* Wait for clock to enable before returning. */ + if (clk->halt_check == DELAY) + udelay(HALT_CHECK_DELAY_US); + else if ( + clk->halt_check == ENABLE || clk->halt_check == HALT || + clk->halt_check == ENABLE_VOTED || clk->halt_check == HALT_VOTED) { + int count; + + /* Wait up to HALT_CHECK_MAX_LOOPS for clock to enable. */ + for (count = HALT_CHECK_MAX_LOOPS; branch_clk_is_halted(clk) && count > 0; + count--) + udelay(1); + } +} + +/* Perform any register operations required to enable the clock. */ +static void __local_clk_enable_reg(struct rcg_clk *clk) +{ + uint32_t reg_val; + + void *const reg = clk->b.ctl_reg; + + if (clk->current_freq == &local_dummy_freq) + dprintf( + CRITICAL, "Attempting to enable %s before setting its rate.", + clk->c.dbg_name); + /* + * Program the NS register, if applicable. NS registers are not + * set in the set_rate path because power can be saved by deferring + * the selection of a clocked source until the clock is enabled. + */ + if (clk->ns_mask) { + reg_val = readl_relaxed(clk->ns_reg); + reg_val &= ~(clk->ns_mask); + reg_val |= (clk->current_freq->ns_val & clk->ns_mask); + writel_relaxed(reg_val, clk->ns_reg); + } + + /* Enable MN counter, if applicable. */ + reg_val = readl_relaxed(reg); + if (clk->current_freq->mnd_en_mask) { + reg_val |= clk->current_freq->mnd_en_mask; + writel_relaxed(reg_val, reg); + } + /* Enable root. */ + if (clk->root_en_mask) { + reg_val |= clk->root_en_mask; + writel_relaxed(reg_val, reg); + } + __branch_clk_enable_reg(&clk->b, clk->c.dbg_name); +} + +/* Enable a clock and any related power rail. */ +int local_clk_enable(struct clk *c) +{ + int rc; + struct rcg_clk *clk = to_rcg_clk(c); + + rc = clk_enable(clk->depends); + if (rc) + goto err_dep; + __local_clk_enable_reg(clk); + clk->enabled = true; +err_dep: + return rc; +} + +/* Disable a clock and any related power rail. */ +void local_clk_disable(struct clk *c) +{ /*TODO: Stub function for now.*/ +} + +/* + * Frequency-related functions + */ + +/* Set a clock's frequency. */ +static int _local_clk_set_rate(struct rcg_clk *clk, struct clk_freq_tbl *nf) +{ + struct clk_freq_tbl *cf; + int rc = 0; + + /* Check if frequency is actually changed. */ + cf = clk->current_freq; + if (nf == cf) + goto unlock; + + if (clk->enabled) { + rc = clk_enable(nf->src_clk); + if (rc) { + goto unlock; + } + } + + /* Perform clock-specific frequency switch operations. */ + ASSERT(clk->set_rate); + clk->set_rate(clk, nf); + + /* + * Current freq must be updated before __local_clk_enable_reg() + * is called to make sure the MNCNTR_EN bit is set correctly. + */ + clk->current_freq = nf; + + /* Enable any clocks that were disabled. */ + if (clk->bank_masks == NULL) { + if (clk->enabled) + __local_clk_enable_reg(clk); + } + +unlock: + return rc; +} + +/* Set a clock to an exact rate. */ +int local_clk_set_rate(struct clk *c, unsigned rate) +{ + struct rcg_clk * clk = to_rcg_clk(c); + struct clk_freq_tbl *nf; + + for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END && nf->freq_hz != rate; nf++) + ; + + if (nf->freq_hz == FREQ_END) + return ERR_INVALID_ARGS; + + return _local_clk_set_rate(clk, nf); +} + +/* Get the currently-set rate of a clock in Hz. */ +unsigned local_clk_get_rate(struct clk *c) +{ + /* TODO: Stub function for now. */ + return 0; +} + +/* Check if a clock is currently enabled. */ +int local_clk_is_enabled(struct clk *clk) { return to_rcg_clk(clk)->enabled; } + +/* Return a supported rate that's at least the specified rate. */ +long local_clk_round_rate(struct clk *c, unsigned rate) +{ + struct rcg_clk * clk = to_rcg_clk(c); + struct clk_freq_tbl *f; + + for (f = clk->freq_tbl; f->freq_hz != FREQ_END; f++) + if (f->freq_hz >= rate) + return f->freq_hz; + + return ERR_INVALID_ARGS; +} + +struct clk *local_clk_get_parent(struct clk *clk) +{ + return to_rcg_clk(clk)->current_freq->src_clk; +} + +/* + * Branch clocks functions + */ +int branch_clk_enable(struct clk *clk) +{ + struct branch_clk *branch = to_branch_clk(clk); + + __branch_clk_enable_reg(&branch->b, branch->c.dbg_name); + branch->enabled = true; + + return 0; +} + +void branch_clk_disable(struct clk *clk) +{ /* TODO: Stub function for now */ +} + +struct clk *branch_clk_get_parent(struct clk *clk) +{ + struct branch_clk *branch = to_branch_clk(clk); + return branch->parent; +} + +int branch_clk_set_parent(struct clk *clk, struct clk *parent) +{ + /* This is a stub function. */ + return 0; +} + +int branch_clk_is_enabled(struct clk *clk) +{ + struct branch_clk *branch = to_branch_clk(clk); + return branch->enabled; +} + +/**/ +/* For clocks with MND dividers. */ +void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf) +{ + uint32_t ns_reg_val, ctl_reg_val; + + /* Assert MND reset. */ + ns_reg_val = readl_relaxed(clk->ns_reg); + ns_reg_val |= BIT(7); + writel_relaxed(ns_reg_val, clk->ns_reg); + + /* Program M and D values. */ + writel_relaxed(nf->md_val, clk->md_reg); + + /* If the clock has a separate CC register, program it. */ + if (clk->ns_reg != clk->b.ctl_reg) { + ctl_reg_val = readl_relaxed(clk->b.ctl_reg); + ctl_reg_val &= ~(clk->ctl_mask); + ctl_reg_val |= nf->ctl_val; + writel_relaxed(ctl_reg_val, clk->b.ctl_reg); + } + + /* Deassert MND reset. */ + ns_reg_val &= ~BIT(7); + writel_relaxed(ns_reg_val, clk->ns_reg); +} + +void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf) +{ + struct bank_masks * banks = clk->bank_masks; + const struct bank_mask_info *new_bank_masks; + const struct bank_mask_info *old_bank_masks; + uint32_t ns_reg_val, ctl_reg_val; + uint32_t bank_sel; + + /* + * Determine active bank and program the other one. If the clock is + * off, program the active bank since bank switching won't work if + * both banks aren't running. + */ + ctl_reg_val = readl_relaxed(clk->b.ctl_reg); + bank_sel = !!(ctl_reg_val & banks->bank_sel_mask); + + /* If clock isn't running, don't switch banks. */ + bank_sel ^= (!clk->enabled || clk->current_freq->freq_hz == 0); + if (bank_sel == 0) { + new_bank_masks = &banks->bank1_mask; + old_bank_masks = &banks->bank0_mask; + } + else { + new_bank_masks = &banks->bank0_mask; + old_bank_masks = &banks->bank1_mask; + } + + ns_reg_val = readl_relaxed(clk->ns_reg); + + /* Assert bank MND reset. */ + ns_reg_val |= new_bank_masks->rst_mask; + writel_relaxed(ns_reg_val, clk->ns_reg); + + /* + * Program NS only if the clock is enabled, since the NS will be set + * as part of the enable procedure and should remain with a low-power + * MUX input selected until then. + */ + if (clk->enabled) { + ns_reg_val &= ~(new_bank_masks->ns_mask); + ns_reg_val |= (nf->ns_val & new_bank_masks->ns_mask); + writel_relaxed(ns_reg_val, clk->ns_reg); + } + + writel_relaxed(nf->md_val, new_bank_masks->md_reg); + + /* Enable counter only if clock is enabled. */ + if (clk->enabled) + ctl_reg_val |= new_bank_masks->mnd_en_mask; + else + ctl_reg_val &= ~(new_bank_masks->mnd_en_mask); + + ctl_reg_val &= ~(new_bank_masks->mode_mask); + ctl_reg_val |= (nf->ctl_val & new_bank_masks->mode_mask); + writel_relaxed(ctl_reg_val, clk->b.ctl_reg); + + /* Deassert bank MND reset. */ + ns_reg_val &= ~(new_bank_masks->rst_mask); + writel_relaxed(ns_reg_val, clk->ns_reg); + + /* + * Switch to the new bank if clock is running. If it isn't, then + * no switch is necessary since we programmed the active bank. + */ + if (clk->enabled && clk->current_freq->freq_hz) { + ctl_reg_val ^= banks->bank_sel_mask; + writel_relaxed(ctl_reg_val, clk->b.ctl_reg); + /* + * Wait at least 6 cycles of slowest bank's clock + * for the glitch-free MUX to fully switch sources. + */ + udelay(1); + + /* Disable old bank's MN counter. */ + ctl_reg_val &= ~(old_bank_masks->mnd_en_mask); + writel_relaxed(ctl_reg_val, clk->b.ctl_reg); + + /* Program old bank to a low-power source and divider. */ + ns_reg_val &= ~(old_bank_masks->ns_mask); + ns_reg_val |= (clk->freq_tbl->ns_val & old_bank_masks->ns_mask); + writel_relaxed(ns_reg_val, clk->ns_reg); + } + + /* + * If this freq requires the MN counter to be enabled, + * update the enable mask to match the current bank. + */ + if (nf->mnd_en_mask) + nf->mnd_en_mask = new_bank_masks->mnd_en_mask; + /* Update the NS mask to match the current bank. */ + clk->ns_mask = new_bank_masks->ns_mask; +} + +void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf) +{ + /* + * Nothing to do for fixed-rate or integer-divider clocks. Any settings + * in NS registers are applied in the enable path, since power can be + * saved by leaving an un-clocked or slowly-clocked source selected + * until the clock is enabled. + */ +} diff --git a/MSM8916Pkg/Drivers/ClockDxe/clock.c b/MSM8916Pkg/Drivers/ClockDxe/clock.c new file mode 100644 index 0000000..732bda3 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/clock.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#include "clock_p.h" + +static struct clk_list msm_clk_list; + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + if (!clk->ops->set_parent) + return 0; + + return clk->ops->set_parent(clk, parent); +} + +struct clk *clk_get_parent(struct clk *clk) +{ + if (!clk->ops->get_parent) + return NULL; + + return clk->ops->get_parent(clk); +} + +int clk_reset(struct clk *clk, enum clk_reset_action action) +{ + if (!clk) + return 0; + + if (!clk->ops->reset) + return 0; + + return clk->ops->reset(clk, action); +} + +/* + * Standard clock functions defined in include/clk.h + */ +int clk_enable(struct clk *clk) +{ + int ret = 0; + struct clk *parent; + + if (!clk) + return 0; + + if (clk->count == 0) { + parent = clk_get_parent(clk); + ret = clk_enable(parent); + if (ret) + goto out; + + if (clk->ops->enable) + ret = clk->ops->enable(clk); + if (ret) { + clk_disable(parent); + goto out; + } + } + clk->count++; +out: + return ret; +} + +void clk_disable(struct clk *clk) +{ + struct clk *parent; + + if (!clk) + return; + + if (clk->count == 0) + goto out; + if (clk->count == 1) { + if (clk->ops->disable) + clk->ops->disable(clk); + parent = clk_get_parent(clk); + clk_disable(parent); + } + clk->count--; +out: + return; +} + +unsigned long clk_get_rate(struct clk *clk) +{ + if (!clk->ops->get_rate) + return 0; + + return clk->ops->get_rate(clk); +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (!clk->ops->set_rate) + return ERR_NOT_VALID; + + return clk->ops->set_rate(clk, rate); +} + +void clk_init(struct clk_lookup *clist, unsigned num) +{ + if (clist && num) { + msm_clk_list.clist = (struct clk_lookup *)clist; + msm_clk_list.num = num; + } +} + +struct clk *clk_get(const char *cid) +{ + unsigned i; + struct clk_lookup *cl = msm_clk_list.clist; + unsigned num = msm_clk_list.num; + + if (!cl || !num) { + dprintf(CRITICAL, "Alert!! clock list not defined!\n"); + return NULL; + } + for (i = 0; i < num; i++, cl++) { + if (!strcmp(cl->con_id, cid)) { + return cl->clk; + } + } + + dprintf(CRITICAL, "Alert!! Requested clock \"%s\" is not supported!\n", cid); + return NULL; +} + +int clk_get_set_enable(char *id, unsigned long rate, bool enable) +{ + int ret = NO_ERROR; + struct clk *cp; + + /* Get clk */ + cp = clk_get(id); + if (!cp) { + dprintf(CRITICAL, "Can't find clock with id: %s\n", id); + ret = ERR_NOT_VALID; + goto get_set_enable_error; + } + + /* Set rate */ + if (rate) { + ret = clk_set_rate(cp, rate); + if (ret) { + dprintf(CRITICAL, "Clock set rate failed.\n"); + goto get_set_enable_error; + } + } + + /* Enable clock */ + if (enable) { + ret = clk_enable(cp); + if (ret) { + dprintf(CRITICAL, "Clock enable failed.\n"); + } + } + +get_set_enable_error: + return ret; +} + +#ifdef DEBUG_CLOCK +struct clk_list *clk_get_list() { return &msm_clk_list; } +#endif diff --git a/MSM8916Pkg/Drivers/ClockDxe/clock_lib2.c b/MSM8916Pkg/Drivers/ClockDxe/clock_lib2.c new file mode 100644 index 0000000..9d2eeae --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/clock_lib2.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include +// Must come in order +#include +#include + +#include "clock_p.h" + +/*=============== CXO clock ops =============*/ +int cxo_clk_enable(struct clk *clk) +{ + /* Nothing to do. */ + return 0; +} + +void cxo_clk_disable(struct clk *clk) +{ + /* Nothing to do. */ + return; +} + +/*=============== Branch clock ops =============*/ + +/* Branch clock enable */ +int clock_lib2_branch_clk_enable(struct clk *clk) +{ + int rc = 0; + uint32_t cbcr_val; + struct branch_clk *bclk = to_branch_clk(clk); + + cbcr_val = readl(bclk->cbcr_reg); + cbcr_val |= CBCR_BRANCH_ENABLE_BIT; + writel(cbcr_val, bclk->cbcr_reg); + + /* wait until status shows it is enabled */ + while (readl(bclk->cbcr_reg) & CBCR_BRANCH_OFF_BIT) + ; + + return rc; +} + +/* Branch clock disable */ +void clock_lib2_branch_clk_disable(struct clk *clk) +{ + uint32_t cbcr_val; + struct branch_clk *bclk = to_branch_clk(clk); + + cbcr_val = readl(bclk->cbcr_reg); + cbcr_val &= ~CBCR_BRANCH_ENABLE_BIT; + writel(cbcr_val, bclk->cbcr_reg); + + /* wait until status shows it is disabled */ + while (!(readl(bclk->cbcr_reg) & CBCR_BRANCH_OFF_BIT)) + ; +} + +/* Branch clock set rate */ +int clock_lib2_branch_set_rate(struct clk *c, unsigned rate) +{ + struct branch_clk *branch = to_branch_clk(c); + + if (!branch->has_sibling) + return clk_set_rate(branch->parent, rate); + + return -1; +} + +/*=============== Root clock ops =============*/ + +/* Root enable */ +int clock_lib2_rcg_enable(struct clk *c) +{ + /* Hardware feedback from branch enable results in root being enabled. + * Nothing to do here. + */ + + return 0; +} + +/* Root set rate: + * Find the entry in the frequecy table corresponding to the requested rate. + * Enable the source clock required for the new frequency. + * Call the set_rate function defined for this particular root clock. + */ +int clock_lib2_rcg_set_rate(struct clk *c, unsigned rate) +{ + struct rcg_clk * rclk = to_rcg_clk(c); + struct clk_freq_tbl *nf; /* new freq */ + int rc = 0; + + /* ck if new freq is in table */ + for (nf = rclk->freq_tbl; nf->freq_hz != FREQ_END && nf->freq_hz != rate; + nf++) + ; + + /* Frequency not found in the table */ + if (nf->freq_hz == FREQ_END) + return ERR_INVALID_ARGS; + + /* Check if frequency is actually changed. */ + if (nf == rclk->current_freq) + return rc; + + /* First enable the source clock for this freq. */ + clk_enable(nf->src_clk); + + /* Perform clock-specific frequency switch operations. */ + ASSERT(rclk->set_rate); + rclk->set_rate(rclk, nf); + + /* update current freq */ + rclk->current_freq = nf; + + return rc; +} + +/* root update config: informs h/w to start using the new config values */ +static void clock_lib2_rcg_update_config(struct rcg_clk *rclk) +{ + uint32_t cmd; + + cmd = readl(rclk->cmd_reg); + cmd |= CMD_UPDATE_BIT; + writel(cmd, rclk->cmd_reg); + + /* Wait for frequency to be updated. */ + while (readl(rclk->cmd_reg) & CMD_UPDATE_MASK) + ; +} + +/* root set rate for clocks with half integer and MND divider */ +void clock_lib2_rcg_set_rate_mnd( + struct rcg_clk *rclk, struct clk_freq_tbl *freq) +{ + uint32_t cfg; + + /* Program MND values */ + writel(freq->m_val, rclk->m_reg); + writel(freq->n_val, rclk->n_reg); + writel(freq->d_val, rclk->d_reg); + + /* setup src select and divider */ + cfg = readl(rclk->cfg_reg); + cfg &= ~(CFG_SRC_SEL_MASK | CFG_SRC_DIV_MASK | CFG_MODE_MASK); + cfg |= freq->div_src_val; + if (freq->n_val != 0) { + cfg |= (CFG_MODE_DUAL_EDGE << CFG_MODE_OFFSET); + } + writel(cfg, rclk->cfg_reg); + + /* Inform h/w to start using the new config. */ + clock_lib2_rcg_update_config(rclk); +} + +/* root set rate for clocks with half integer divider */ +void clock_lib2_rcg_set_rate_hid( + struct rcg_clk *rclk, struct clk_freq_tbl *freq) +{ + uint32_t cfg; + + /* setup src select and divider */ + cfg = readl(rclk->cfg_reg); + cfg &= ~(CFG_SRC_SEL_MASK | CFG_SRC_DIV_MASK); + cfg |= freq->div_src_val; + writel(cfg, rclk->cfg_reg); + + clock_lib2_rcg_update_config(rclk); +} + +/*=============== Vote clock ops =============*/ + +/* Vote clock enable */ +int clock_lib2_vote_clk_enable(struct clk *c) +{ + uint32_t vote_regval; + uint32_t val; + struct vote_clk *vclk = to_local_vote_clk(c); + + vote_regval = readl(vclk->vote_reg); + vote_regval |= vclk->en_mask; + writel_relaxed(vote_regval, vclk->vote_reg); + do { + val = readl(vclk->cbcr_reg); + val &= BRANCH_CHECK_MASK; + } + /* wait until status shows it is enabled */ + while ((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL)); + + return 0; +} + +/* Vote clock disable */ +void clock_lib2_vote_clk_disable(struct clk *c) +{ + uint32_t vote_regval; + struct vote_clk *vclk = to_local_vote_clk(c); + + vote_regval = readl(vclk->vote_reg); + vote_regval &= ~vclk->en_mask; + writel_relaxed(vote_regval, vclk->vote_reg); +} + +/* Reset clock */ +static int +__clock_lib2_branch_clk_reset(uint32_t bcr_reg, enum clk_reset_action action) +{ + uint32_t reg; + int ret = 0; + + reg = readl(bcr_reg); + + switch (action) { + case CLK_RESET_ASSERT: + reg |= BIT(0); + break; + case CLK_RESET_DEASSERT: + reg &= ~BIT(0); + break; + default: + ret = 1; + } + + writel(reg, bcr_reg); + + /* Wait for writes to go through */ + dmb(); + + return ret; +} + +int clock_lib2_reset_clk_reset(struct clk *c, enum clk_reset_action action) +{ + struct reset_clk *rst = to_reset_clk(c); + + if (!rst) + return 0; + + return __clock_lib2_branch_clk_reset(rst->bcr_reg, action); +} + +int clock_lib2_branch_clk_reset(struct clk *c, enum clk_reset_action action) +{ + struct branch_clk *bclk = to_branch_clk(c); + + if (!bclk) + return 0; + + return __clock_lib2_branch_clk_reset((uint32_t)bclk->bcr_reg, action); +} diff --git a/MSM8916Pkg/Drivers/ClockDxe/clock_p.h b/MSM8916Pkg/Drivers/ClockDxe/clock_p.h new file mode 100644 index 0000000..851ba20 --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/clock_p.h @@ -0,0 +1,110 @@ +#ifndef _CLOCK_PRIVATE_H +#define _CLOCK_PRIVATE_H + +/** + * clk_get - lookup and obtain a reference to a clock producer. + * @dev: device for clock "consumer" + * @id: clock comsumer ID + * + * Returns a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. (IOW, @id may be identical strings, but + * clk_get may return different clock producers depending on @dev.) + * + * Drivers must assume that the clock source is not enabled. + * + * clk_get should not be called from within interrupt context. + */ +struct clk *clk_get(const char *id); + + +/** + * clk_enable - inform the system when the clock source should be running. + * @clk: clock source + * + * If the clock can not be enabled/disabled, this should return success. + * + * Returns success (0) or negative errno. + */ +int clk_enable(struct clk *clk); + +/** + * clk_disable - inform the system when the clock source is no longer required. + * @clk: clock source + * + * Inform the system that a clock source is no longer required by + * a driver and may be shut down. + * + * Implementation detail: if the clock source is shared between + * multiple drivers, clk_enable() calls must be balanced by the + * same number of clk_disable() calls for the clock source to be + * disabled. + */ +void clk_disable(struct clk *clk); + +/** + * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. + * This is only valid once the clock source has been enabled. + * @clk: clock source + */ +unsigned long clk_get_rate(struct clk *clk); + +/** + * clk_set_rate - set the clock rate for a clock source + * @clk: clock source + * @rate: desired clock rate in Hz + * + * Returns success (0) or negative errno. + */ +int clk_set_rate(struct clk *clk, unsigned long rate); + +/** + * clk_set_parent - set the parent clock source for this clock + * @clk: clock source + * @parent: parent clock source + * + * Returns success (0) or negative errno. + */ +int clk_set_parent(struct clk *clk, struct clk *parent); + +/** + * clk_get_parent - get the parent clock source for this clock + * @clk: clock source + * + * Returns struct clk corresponding to parent clock source, or + * valid IS_ERR() condition containing errno. + */ +struct clk *clk_get_parent(struct clk *clk); + +/** + * clk_get_set_enable - + * -- get the clock. + * -- set the rate to @rate if @rate is non-zero + * -- enable the clock if @enable = ture; + * @id: clock identifier (char *) + * @rate: desired clock rate in Hz + * + * Returns success (0) or negative errno. + */ +int clk_get_set_enable(char *id, unsigned long rate, bool enable); + +#ifdef DEBUG_CLOCK +struct clk_list *clk_get_list(void); +#endif + +/** + * clk_init - register all the clocks in the system. + * @clist: pointer to clock list + * @num: number of clocks in the list + */ +void clk_init(struct clk_lookup *clist, unsigned num); + +/** + * clk_reset - Reset block using BCR + * @clk: pointer to clock + * @action: clock assert or deassert + */ +int clk_reset(struct clk *clk, enum clk_reset_action); + +#endif // _CLOCK_PRIVATE_H diff --git a/MSM8916Pkg/Drivers/ClockDxe/clock_pll.c b/MSM8916Pkg/Drivers/ClockDxe/clock_pll.c new file mode 100644 index 0000000..cbf919c --- /dev/null +++ b/MSM8916Pkg/Drivers/ClockDxe/clock_pll.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +// Must come in order +#include + +/* + * pll_vote_clk functions + */ +int pll_vote_clk_enable(struct clk *clk) +{ + uint32_t ena; + struct pll_vote_clk *pll = to_pll_vote_clk(clk); + + ena = readl_relaxed(pll->en_reg); + ena |= pll->en_mask; + writel_relaxed(ena, pll->en_reg); + + /* Wait until PLL is enabled */ + while ((readl_relaxed(pll->status_reg) & pll->status_mask) == 0) + ; + + return 0; +} + +void pll_vote_clk_disable(struct clk *clk) +{ + uint32_t ena; + struct pll_vote_clk *pll = to_pll_vote_clk(clk); + + ena = readl_relaxed(pll->en_reg); + ena &= ~(pll->en_mask); + writel_relaxed(ena, pll->en_reg); +} + +unsigned pll_vote_clk_get_rate(struct clk *clk) +{ + struct pll_vote_clk *pll = to_pll_vote_clk(clk); + return pll->rate; +} + +struct clk *pll_vote_clk_get_parent(struct clk *clk) +{ + struct pll_vote_clk *pll = to_pll_vote_clk(clk); + return pll->parent; +} + +int pll_vote_clk_is_enabled(struct clk *clk) +{ + struct pll_vote_clk *pll = to_pll_vote_clk(clk); + return !!(readl_relaxed(pll->status_reg) & pll->status_mask); +} + +/* + * PLLs functions + */ +int pll_clk_enable(struct clk *clk) +{ + uint32_t mode; + struct pll_clk *pll = to_pll_clk(clk); + + mode = readl_relaxed(pll->mode_reg); + /* Disable PLL bypass mode. */ + mode |= BIT(1); + writel_relaxed(mode, pll->mode_reg); + + /* + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. Delay 10us just to be safe. + */ + udelay(10); + + /* De-assert active-low PLL reset. */ + mode |= BIT(2); + writel_relaxed(mode, pll->mode_reg); + + /* Wait until PLL is locked. */ + udelay(50); + + /* Enable PLL output. */ + mode |= BIT(0); + writel_relaxed(mode, pll->mode_reg); + + return 0; +} + +void pll_clk_disable(struct clk *clk) +{ + uint32_t mode; + struct pll_clk *pll = to_pll_clk(clk); + + /* + * Disable the PLL output, disable test mode, enable + * the bypass mode, and assert the reset. + */ + mode = readl_relaxed(pll->mode_reg); + mode &= ~BM(3, 0); + writel_relaxed(mode, pll->mode_reg); +} + +unsigned pll_clk_get_rate(struct clk *clk) +{ + struct pll_clk *pll = to_pll_clk(clk); + return pll->rate; +} + +struct clk *pll_clk_get_parent(struct clk *clk) +{ + struct pll_clk *pll = to_pll_clk(clk); + return pll->parent; +} diff --git a/MSM8916Pkg/Include/Chipset/clock-local.h b/MSM8916Pkg/Include/Chipset/clock-local.h new file mode 100644 index 0000000..6182e5a --- /dev/null +++ b/MSM8916Pkg/Include/Chipset/clock-local.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CLOCK_LOCAL_H +#define CLOCK_LOCAL_H + +struct clk; +struct clk_ops; + +#define FREQ_END (UINT32_MAX - 1) +#define F_END \ + { \ + .freq_hz = FREQ_END, \ + } + +#define container_of(ptr, type, member) \ + ((type *)((addr_t)(ptr)-offsetof(type, member))) + +/* + * Bit manipulation macros + */ +#define BM(msb, lsb) \ + (((((uint32_t)-1) << (31 - msb)) >> (31 - msb + lsb)) << lsb) +#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb)) + +/* + * Halt/Status Checking Mode Macros + */ +#define HALT 0 /* Bit pol: 1 = halted */ +#define NOCHECK 1 /* No bit to check, do nothing */ +#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */ +#define ENABLE 3 /* Bit pol: 1 = running */ +#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */ +#define DELAY 5 /* No bit to check, just delay */ + +/* + * Variables from clock-local driver + */ +extern struct fixed_clk gnd_clk; + +/* + * Generic frequency-definition structs and macros + */ +struct clk_freq_tbl { + const uint32_t freq_hz; + struct clk * src_clk; + const uint32_t md_val; + const uint32_t ns_val; + const uint32_t ctl_val; + uint32_t mnd_en_mask; + void *const extra_freq_data; +}; + +extern struct clk_freq_tbl local_dummy_freq; + +/* Some clocks have two banks to avoid glitches when switching frequencies. + * The unused bank is programmed while running on the other bank, and + * switched to afterwards. The following two structs describe the banks. */ +struct bank_mask_info { + void *const md_reg; + const uint32_t ns_mask; + const uint32_t rst_mask; + const uint32_t mnd_en_mask; + const uint32_t mode_mask; +}; + +struct bank_masks { + const uint32_t bank_sel_mask; + const struct bank_mask_info bank0_mask; + const struct bank_mask_info bank1_mask; +}; + +/** + * struct branch - branch on/off + * @ctl_reg: clock control register + * @en_mask: ORed with @ctl_reg to enable the clock + * @halt_reg: halt register + * @halt_check: type of halt check to perform + * @halt_bit: ANDed with @halt_reg to test for clock halted + * @reset_reg: reset register + * @reset_mask: ORed with @reset_reg to reset the clock domain + */ +struct branch { + void *const ctl_reg; + const uint32_t en_mask; + + void *const halt_reg; + const uint16_t halt_check; + const uint16_t halt_bit; + + void *const reset_reg; + const uint32_t reset_mask; +}; + +/* + * Generic clock-definition struct and macros + */ +struct rcg_clk { + bool enabled; + void *const ns_reg; + void *const md_reg; + + const uint32_t root_en_mask; + uint32_t ns_mask; + const uint32_t ctl_mask; + struct bank_masks *const bank_masks; + + void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *); + struct clk_freq_tbl *freq_tbl; + struct clk_freq_tbl *current_freq; + + struct clk * depends; + struct branch b; + struct clk c; +}; + +static inline struct rcg_clk *to_rcg_clk(struct clk *clk) +{ + return container_of(clk, struct rcg_clk, c); +} + +/** + * struct fixed_clk - fixed rate clock (used for crystal oscillators) + * @rate: output rate + * @c: clk + */ +struct fixed_clk { + unsigned long rate; + struct clk c; +}; + +static inline struct fixed_clk *to_fixed_clk(struct clk *clk) +{ + return container_of(clk, struct fixed_clk, c); +} + +static inline unsigned fixed_clk_get_rate(struct clk *clk) +{ + struct fixed_clk *f = to_fixed_clk(clk); + return f->rate; +} + +/** + * struct branch_clk - branch + * @enabled: true if clock is on, false otherwise + * @b: branch + * @parent: clock source + * @c: clk + * + * An on/off switch with a rate derived from the parent. + */ +struct branch_clk { + bool enabled; + struct branch b; + struct clk * parent; + struct clk c; +}; + +static inline struct branch_clk *to_branch_clk(struct clk *clk) +{ + return container_of(clk, struct branch_clk, c); +} + +int branch_clk_enable(struct clk *clk); +void branch_clk_disable(struct clk *clk); +struct clk *branch_clk_get_parent(struct clk *clk); +int branch_clk_set_parent(struct clk *clk, struct clk *parent); +int branch_clk_is_enabled(struct clk *clk); +void branch_clk_auto_off(struct clk *clk); +int branch_clk_reset(struct clk *c, enum clk_reset_action action); + +/** + * struct measure_clk - for rate measurement debug use + * @sample_ticks: sample period in reference clock ticks + * @multiplier: measurement scale-up factor + * @divider: measurement scale-down factor + * @c: clk + */ +struct measure_clk { + uint64_t sample_ticks; + uint32_t multiplier; + uint32_t divider; + struct clk c; +}; + +extern struct clk_ops clk_ops_measure; + +static inline struct measure_clk *to_measure_clk(struct clk *clk) +{ + return container_of(clk, struct measure_clk, c); +} + +/* + * clk_ops APIs + */ +int local_clk_enable(struct clk *c); +void local_clk_disable(struct clk *c); +int local_clk_set_rate(struct clk *c, unsigned rate); +unsigned local_clk_get_rate(struct clk *c); +int local_clk_is_enabled(struct clk *clk); +long local_clk_round_rate(struct clk *c, unsigned rate); +struct clk *local_clk_get_parent(struct clk *clk); + +/* + * Generic set-rate implementations + */ +void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf); +void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf); +void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf); +#endif diff --git a/MSM8916Pkg/Include/Chipset/clock.h b/MSM8916Pkg/Include/Chipset/clock.h new file mode 100644 index 0000000..b3da8d1 --- /dev/null +++ b/MSM8916Pkg/Include/Chipset/clock.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CLOCK_H +#define CLOCK_H + +enum clk_reset_action { CLK_RESET_DEASSERT = 0, CLK_RESET_ASSERT = 1 }; + +struct clk; +struct clk_ops { + int (*enable)(struct clk *clk); + void (*disable)(struct clk *clk); + void (*auto_off)(struct clk *clk); + int (*reset)(struct clk *clk, enum clk_reset_action action); + int (*set_rate)(struct clk *clk, unsigned rate); + int (*set_min_rate)(struct clk *clk, unsigned rate); + int (*set_max_rate)(struct clk *clk, unsigned rate); + int (*set_flags)(struct clk *clk, unsigned flags); + unsigned (*get_rate)(struct clk *clk); + int (*list_rate)(struct clk *clk, unsigned n); + int (*is_enabled)(struct clk *clk); + long (*round_rate)(struct clk *clk, unsigned rate); + int (*set_parent)(struct clk *clk, struct clk *parent); + struct clk *(*get_parent)(struct clk *clk); + bool (*is_local)(struct clk *clk); +}; + +/** + * struct clk + * @count: enable refcount + * @lock: protects clk_enable()/clk_disable() path and @count + */ +struct clk { + uint32_t flags; + uint32_t rate; + struct clk_ops *ops; + const char * dbg_name; + unsigned count; +}; + +struct clk_lookup { + const char *con_id; + struct clk *clk; +}; + +struct clk_list { + struct clk_lookup *clist; + unsigned num; +}; + +#define CLK_LOOKUP(con, c) \ + { \ + .con_id = con, .clk = &c \ + } + +#endif diff --git a/MSM8916Pkg/Include/Chipset/clock_lib2.h b/MSM8916Pkg/Include/Chipset/clock_lib2.h new file mode 100644 index 0000000..262f14c --- /dev/null +++ b/MSM8916Pkg/Include/Chipset/clock_lib2.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2012-2014, Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CLOCK_LIB2_H +#define __CLOCK_LIB2_H + +/* + * Bit manipulation macros + */ +#define BM(msb, lsb) \ + (((((uint32_t)-1) << (31 - msb)) >> (31 - msb + lsb)) << lsb) +#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb)) + +#define container_of(ptr, type, member) \ + ((type *)((addr_t)(ptr)-offsetof(type, member))) + +/* Frequency Macros */ +#define FREQ_END (UINT32_MAX - 1) +#define F_END \ + { \ + .freq_hz = FREQ_END, \ + } + +/* F(frequency, source, div, m, n) */ +#define F(f, s, div, m, n) \ + { \ + .freq_hz = (f), .src_clk = &s##_clk_src.c, .m_val = (m), \ + .n_val = ~((n) - (m)) * !!(n), .d_val = ~(n), \ + .div_src_val = \ + BVAL(4, 0, (int)(2 * (div)-1)) | BVAL(10, 8, s##_source_val), \ + } + +/* F(frequency, source, div, m, n) */ +#define F_EXT_SRC(f, s, div, m, n) \ + { \ + .freq_hz = (f), .m_val = (m), .n_val = ~((n) - (m)) * !!(n), \ + .d_val = ~(n), \ + .div_src_val = \ + BVAL(4, 0, (int)(2 * (div)-1)) | BVAL(10, 8, s##_source_val), \ + } + +/* F_MM(frequency, source, div, m, n) */ +#define F_MM(f, s, div, m, n) \ + { \ + .freq_hz = (f), .src_clk = &s##_clk_src.c, .m_val = (m), \ + .n_val = ~((n) - (m)) * !!(n), .d_val = ~(n), \ + .div_src_val = \ + BVAL(4, 0, (int)(2 * (div)-1)) | BVAL(10, 8, s##_mm_source_val), \ + } + +#define F_MDSS(f, s, div, m, n) \ + { \ + .freq_hz = (f), .m_val = (m), .n_val = ~((n) - (m)) * !!(n), \ + .d_val = ~(n), \ + .div_src_val = \ + BVAL(4, 0, (int)(2 * (div)-1)) | BVAL(10, 8, s##_mm_source_val), \ + } + +/* Branch Clock Bits */ +#define CBCR_BRANCH_ENABLE_BIT BIT(0) +#define CBCR_BRANCH_OFF_BIT BIT(31) +#define BRANCH_CHECK_MASK BM(31, 28) +#define BRANCH_ON_VAL BVAL(31, 28, 0x0) +#define BRANCH_NOC_FSM_ON_VAL BVAL(31, 28, 0x2) + +/* Root Clock Bits */ +#define CMD_UPDATE_BIT BIT(0) +#define CMD_UPDATE_MASK 1 + +#define CFG_SRC_DIV_OFFSET 0 +#define CFG_SRC_DIV_MASK (0x1F << CFG_SRC_DIV_OFFSET) + +#define CFG_SRC_SEL_OFFSET 8 +#define CFG_SRC_SEL_MASK (0x3 << CFG_SRC_SEL_OFFSET) + +#define CFG_MODE_DUAL_EDGE 0x2 + +#define CFG_MODE_OFFSET 12 +#define CFG_MODE_MASK (0x3 << CFG_MODE_OFFSET) + +/* + * Generic frequency-definition structs and macros + */ +struct clk_freq_tbl { + + const uint32_t freq_hz; + struct clk * src_clk; + const uint32_t div_src_val; + + /* TODO: find out if sys_vdd is needed. */ + + const uint32_t m_val; + const uint32_t n_val; /* not_n_minus_m_val */ + const uint32_t d_val; /* not_2d_val */ +}; + +/* Fixed clock */ +struct fixed_clk { + struct clk c; +}; + +/* Branch clock */ +struct branch_clk { + + uint32_t *const bcr_reg; + uint32_t *const cbcr_reg; + + void (*set_rate)(struct branch_clk *, struct clk_freq_tbl *); + + struct clk *parent; + struct clk c; + + int has_sibling; + uint32_t cur_div; + uint32_t max_div; + uint32_t halt_check; +}; + +/* Root Clock */ +struct rcg_clk { + + /* RCG registers for this clock */ + + uint32_t *const cmd_reg; /* Command reg */ + uint32_t *const cfg_reg; /* Config reg */ + uint32_t *const m_reg; /* m */ + uint32_t *const n_reg; /* not (n-m) */ + uint32_t *const d_reg; /* not (2d) */ + + /* set rate function for this clock */ + void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *); + + /* freq table */ + struct clk_freq_tbl *freq_tbl; + struct clk_freq_tbl *current_freq; + + struct clk c; +}; + +/* Vote Clock */ +struct vote_clk { + + uint32_t *const cbcr_reg; + uint32_t *const vote_reg; + uint32_t en_mask; + + struct clk c; +}; + +struct reset_clk { + uint32_t bcr_reg; + struct clk c; +}; + +static inline struct reset_clk *to_reset_clk(struct clk *clk) +{ + return container_of(clk, struct reset_clk, c); +} + +static inline struct rcg_clk *to_rcg_clk(struct clk *clk) +{ + return container_of(clk, struct rcg_clk, c); +} + +static inline struct branch_clk *to_branch_clk(struct clk *clk) +{ + return container_of(clk, struct branch_clk, c); +} + +static inline struct vote_clk *to_local_vote_clk(struct clk *clk) +{ + return container_of(clk, struct vote_clk, c); +} + +/* RCG clock functions */ +int clock_lib2_rcg_enable(struct clk *c); +int clock_lib2_rcg_set_rate(struct clk *c, unsigned rate); +void clock_lib2_rcg_set_rate_mnd( + struct rcg_clk *rclk, struct clk_freq_tbl *freq); +void clock_lib2_rcg_set_rate_hid( + struct rcg_clk *rclk, struct clk_freq_tbl *freq); + +/* CXO clock functions */ +int cxo_clk_enable(struct clk *clk); +void cxo_clk_disable(struct clk *clk); + +/* Branch clock functions */ +int clock_lib2_branch_clk_enable(struct clk *clk); +void clock_lib2_branch_clk_disable(struct clk *clk); +int clock_lib2_branch_set_rate(struct clk *c, unsigned rate); + +/* Vote clock functions*/ +int clock_lib2_vote_clk_enable(struct clk *c); +void clock_lib2_vote_clk_disable(struct clk *c); +/* clock reset function */ +int clock_lib2_reset_clk_reset(struct clk *c, enum clk_reset_action action); +int clock_lib2_branch_clk_reset(struct clk *c, enum clk_reset_action action); +#endif diff --git a/MSM8916Pkg/Include/Chipset/clock_pll.h b/MSM8916Pkg/Include/Chipset/clock_pll.h new file mode 100644 index 0000000..e08fc2f --- /dev/null +++ b/MSM8916Pkg/Include/Chipset/clock_pll.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CLOCK_PLL_H +#define CLOCK_PLL_H + +/* + * Bit manipulation macros + */ +#define BM(msb, lsb) \ + (((((uint32_t)-1) << (31 - msb)) >> (31 - msb + lsb)) << lsb) +#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb)) + +struct clk; +struct clk_ops; + +#define container_of(ptr, type, member) \ + ((type *)((addr_t)(ptr)-offsetof(type, member))) + +/** + * struct pll_vote_clk - phase locked loop (HW voteable) + * @rate: output rate + * @en_reg: enable register + * @en_mask: ORed with @en_reg to enable the clock + * @status_reg: status register + * @parent: clock source + * @c: clk + */ +struct pll_vote_clk { + unsigned long rate; + + void *const en_reg; + const uint32_t en_mask; + + void *const status_reg; + const uint32_t status_mask; + + struct clk *parent; + struct clk c; +}; + +static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *clk) +{ + return container_of(clk, struct pll_vote_clk, c); +} + +/** + * struct pll_clk - phase locked loop + * @rate: output rate + * @mode_reg: enable register + * @parent: clock source + * @c: clk + */ +struct pll_clk { + unsigned long rate; + + void *const mode_reg; + + struct clk *parent; + struct clk c; +}; + +static inline struct pll_clk *to_pll_clk(struct clk *clk) +{ + return container_of(clk, struct pll_clk, c); +} + +int pll_vote_clk_enable(struct clk *clk); +void pll_vote_clk_disable(struct clk *clk); +unsigned pll_vote_clk_get_rate(struct clk *clk); +struct clk *pll_vote_clk_get_parent(struct clk *clk); +int pll_vote_clk_is_enabled(struct clk *clk); + +int pll_clk_enable(struct clk *clk); +void pll_clk_disable(struct clk *clk); +unsigned pll_clk_get_rate(struct clk *clk); +struct clk *pll_clk_get_parent(struct clk *clk); +#endif diff --git a/MSM8916Pkg/Include/Library/LKEnvLib.h b/MSM8916Pkg/Include/Library/LKEnvLib.h new file mode 100644 index 0000000..93c6f8a --- /dev/null +++ b/MSM8916Pkg/Include/Library/LKEnvLib.h @@ -0,0 +1,111 @@ +#ifndef __LIBRARY_LKENV_H__ +#define __LIBRARY_LKENV_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "minstdbool.h" +#include "minstdint.h" + + +#define REG32(addr) ((volatile uint32_t *)(addr)) +#define writel_rt(v, a) (*REG32(a) = (v)) +#define readl_rt(a) (*REG32(a)) + +#define writel(v, a) MmioWrite32((UINTN)(a), (UINT32)(v)) +#define readl(a) MmioRead32((UINTN)(a)) +#define writeb(v, a) MmioWrite8((UINTN)(a), (UINT8)(v)) +#define readb(a) MmioRead8((UINTN)(a)) +#define writehw(v, a) MmioWrite16((UINTN)(a), (UINT16)(v)) +#define readhw(a) MmioRead16((UINTN)(a)) +#define RMWREG32(addr, startbit, width, val) \ + writel( \ + (readl(addr) & ~(((1 << (width)) - 1) << (startbit))) | \ + ((val) << (startbit)), \ + addr) +#define BIT(bit) (1 << (bit)) + +#ifdef MSM_SECURE_IO +#define readl_relaxed secure_readl +#define writel_relaxed secure_writel +#else +#define readl_relaxed readl +#define writel_relaxed writel +#endif + +#define NO_ERROR 0 +#define ERROR -1 +#define ERR_NOT_FOUND -2 +#define ERR_NO_MEMORY -5 +#define ERR_NOT_VALID -7 +#define ERR_INVALID_ARGS -8 +#define ERR_IO -20 +#define ERR_NOT_SUPPORTED -24 + +#include "minstdbool.h" +#include "minstring.h" + +#define va_list VA_LIST +#define offsetof(type, member) OFFSET_OF(type, member) +#define __PACKED __attribute__((packed)) + +#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1)) +#define ROUNDDOWN(a, b) ((a) & ~((b)-1)) +#define CACHE_LINE (ArmDataCacheLineLength()) +#define IS_CACHE_LINE_ALIGNED(addr) !((UINTN)(addr) & (CACHE_LINE - 1)) + +#define snprintf(s, n, fmt, ...) \ + ((int)AsciiSPrint((s), (n), (fmt), ##__VA_ARGS__)) + +/* debug levels */ +#define CRITICAL DEBUG_ERROR +#define ALWAYS DEBUG_ERROR +#define INFO DEBUG_INFO +#define SPEW DEBUG_VERBOSE + +#if !defined(MDEPKG_NDEBUG) +#define dprintf(level, fmt, ...) \ + do { \ + if (DebugPrintEnabled()) { \ + CHAR8 __printbuf[100]; \ + UINTN __printindex; \ + CONST CHAR8 *__fmtptr = (fmt); \ + UINTN __fmtlen = AsciiStrSize(__fmtptr); \ + CopyMem(__printbuf, __fmtptr, __fmtlen); \ + __printbuf[__fmtlen - 1] = 0; \ + for (__printindex = 1; __printbuf[__printindex]; __printindex++) { \ + if (__printbuf[__printindex - 1] == '%' && \ + __printbuf[__printindex] == 's') \ + __printbuf[__printindex] = 'a'; \ + } \ + DEBUG(((level), __printbuf, ##__VA_ARGS__)); \ + } \ + } while (0) +#else +#define dprintf(level, fmt, ...) +#endif + +#define ntohl(n) SwapBytes32(n) + +#define dmb() ArmDataMemoryBarrier() +#define dsb() ArmDataSynchronizationBarrier() + +#define mdelay(msecs) MicroSecondDelay((msecs)*1000) +#define udelay(usecs) MicroSecondDelay((usecs)) + +#define arch_clean_invalidate_cache_range(start, len) \ + WriteBackInvalidateDataCacheRange((VOID *)(UINTN)(start), (UINTN)(len)) +#define arch_invalidate_cache_range(start, len) \ + InvalidateDataCacheRange((VOID *)(UINTN)(start), (UINTN)(len)); + +#define __ALWAYS_INLINE __attribute__((always_inline)) + +#define ROUND_TO_PAGE(x) (x & (~(EFI_PAGE_SIZE - 1))) + +#endif diff --git a/MSM8916Pkg/Include/Library/QcomClockLib.h b/MSM8916Pkg/Include/Library/QcomClockLib.h new file mode 100644 index 0000000..89b9965 --- /dev/null +++ b/MSM8916Pkg/Include/Library/QcomClockLib.h @@ -0,0 +1,12 @@ +#ifndef __LIBRARY_QCOM_CLOCK_LIB_H__ +#define __LIBRARY_QCOM_CLOCK_LIB_H__ + +#include + +RETURN_STATUS +EFIAPI +ClockImplLibInitialize(VOID); + +extern QCOM_CLOCK_PROTOCOL *gClock; + +#endif diff --git a/MSM8916Pkg/Include/Library/QcomPlatformClockInitLib.h b/MSM8916Pkg/Include/Library/QcomPlatformClockInitLib.h new file mode 100644 index 0000000..d37154b --- /dev/null +++ b/MSM8916Pkg/Include/Library/QcomPlatformClockInitLib.h @@ -0,0 +1,11 @@ +#ifndef __LIBRARY_QCOM_PLATFORM_CLOCKINIT_LIB_H__ +#define __LIBRARY_QCOM_PLATFORM_CLOCKINIT_LIB_H__ + +#include +#include + +EFI_STATUS +EFIAPI +LibQcomPlatformClockInit(struct clk_lookup **clist, unsigned *num); + +#endif diff --git a/MSM8916Pkg/Include/Library/minstdbool.h b/MSM8916Pkg/Include/Library/minstdbool.h new file mode 100644 index 0000000..81bcf7d --- /dev/null +++ b/MSM8916Pkg/Include/Library/minstdbool.h @@ -0,0 +1,11 @@ +#ifndef __MIN_STDBOOL_H__ +#define __MIN_STDBOOL_H__ + +#include + +typedef BOOLEAN bool; + +#define true TRUE +#define false FALSE + +#endif diff --git a/MSM8916Pkg/Include/Library/minstdint.h b/MSM8916Pkg/Include/Library/minstdint.h new file mode 100644 index 0000000..2a017ea --- /dev/null +++ b/MSM8916Pkg/Include/Library/minstdint.h @@ -0,0 +1,70 @@ +#ifndef __MIN_STDINT_H__ +#define __MIN_STDINT_H__ + +#include + +typedef UINTN size_t; + +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef INT32 int32_t; +typedef INT64 int64_t; + +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; + +typedef UINTN addr_t; +typedef UINTN paddr_t; + +typedef UINT8 u8; +typedef UINT16 u16; +typedef UINT32 u32; +typedef UINT64 u64; + +#ifndef INT16_MIN +#define INT16_MIN MIN_INT16 +#endif + +#ifndef INT16_MAX +#define INT16_MAX MAX_INT16 +#endif + +#ifndef UINT16_MIN +#define UINT16_MIN MIN_UINT16 +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX MAX_UINT16 +#endif + +#ifndef INT32_MIN +#define INT32_MIN MIN_INT32 +#endif + +#ifndef INT32_MAX +#define INT32_MAX MAX_INT32 +#endif + +#ifndef UINT32_MIN +#define UINT32_MIN MIN_UINT32 +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX MAX_UINT32 +#endif + +#ifndef UINT_MAX +#define UINT_MAX MAX_UINTN +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX (~0UL) +#endif + +#ifndef LONG_MAX +#define LONG_MAX ((long)(~0UL >> 1)) +#endif + +#endif diff --git a/MSM8916Pkg/Include/Library/minstring.h b/MSM8916Pkg/Include/Library/minstring.h new file mode 100644 index 0000000..079f852 --- /dev/null +++ b/MSM8916Pkg/Include/Library/minstring.h @@ -0,0 +1,17 @@ +#ifndef __MIN_STRING_H__ +#define __MIN_STRING_H__ + +#include +#include + +#define strcmp(s1, s2) ((int)AsciiStrCmp((s1), (s2))) +#define strncmp(s1, s2, n) ((int)AsciiStrnCmp((s1), (s2), (n))) +#define strlen(s) ((size_t)AsciiStrLen((s))) +#define strlcpy(dst, src, n) AsciiStrCpyS((dst), (n), (src)) +#define strstr(s1, s2) AsciiStrStr((s1), (s2)) +#define memset(s, c, n) SetMem((s), (UINTN)(n), (UINT8)(c)) +#define memcpy(s1, s2, n) CopyMem((s1), (s2), (n)) +#define memmove(s1, s2, n) CopyMem((s1), (s2), (n)) +#define memcmp(s1, s2, n) ((int)CompareMem((s1), (s2), (n))) + +#endif diff --git a/MSM8916Pkg/Include/Platform/clock.h b/MSM8916Pkg/Include/Platform/clock.h new file mode 100644 index 0000000..c37d59e --- /dev/null +++ b/MSM8916Pkg/Include/Platform/clock.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MSM8916_CLOCK_H +#define __MSM8916_CLOCK_H + +#include +#include + +#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC + +#define REG_MM(off) (CLK_CTL_BASE + (off)) + +#define MDP_GDSCR REG_MM(0x4D078) +#define GDSC_POWER_ON_BIT BIT(31) +#define GDSC_POWER_ON_STATUS_BIT BIT(29) +#define GDSC_EN_FEW_WAIT_MASK (0x0F << 16) +#define GDSC_EN_FEW_WAIT_256_MASK BIT(19) + +#define VSYNC_CMD_RCGR REG_MM(0x4D02C) +#define VSYNC_CFG_RCGR REG_MM(0x4D030) +#define MDSS_VSYNC_CBCR REG_MM(0x4D090) + +#define MDP_CMD_RCGR REG_MM(0x4D014) +#define MDP_CFG_RCGR REG_MM(0x4D018) +#define MDP_CBCR REG_MM(0x4D088) +#define MDP_AHB_CBCR REG_MM(0x4D07C) +#define MDP_AXI_CBCR REG_MM(0x4D080) + +#define DSI_BYTE0_CMD_RCGR REG_MM(0x4D044) +#define DSI_BYTE0_CFG_RCGR REG_MM(0x4D048) +#define DSI_BYTE0_CBCR REG_MM(0x4D094) +#define DSI_ESC0_CMD_RCGR REG_MM(0x4D05C) +#define DSI_ESC0_CFG_RCGR REG_MM(0x4D060) +#define DSI_ESC0_CBCR REG_MM(0x4D098) +#define DSI_PIXEL0_CMD_RCGR REG_MM(0x4D000) +#define DSI_PIXEL0_CFG_RCGR REG_MM(0x4D004) +#define DSI_PIXEL0_CBCR REG_MM(0x4D084) +#define DSI_PIXEL0_M REG_MM(0x4D008) +#define DSI_PIXEL0_N REG_MM(0x4D00C) +#define DSI_PIXEL0_D REG_MM(0x4D010) + +#define DSI_BYTE1_CMD_RCGR REG_MM(0x4D0B0) +#define DSI_BYTE1_CFG_RCGR REG_MM(0x4D0B4) +#define DSI_BYTE1_CBCR REG_MM(0x4D0A0) +#define DSI_ESC1_CMD_RCGR REG_MM(0x4D0A8) +#define DSI_ESC1_CFG_RCGR REG_MM(0x4D0AC) +#define DSI_ESC1_CBCR REG_MM(0x4D09C) +#define DSI_PIXEL1_CMD_RCGR REG_MM(0x4D0B8) +#define DSI_PIXEL1_CFG_RCGR REG_MM(0x4D0BC) +#define DSI_PIXEL1_CBCR REG_MM(0x4D0A4) +#define DSI_PIXEL1_M REG_MM(0x4D0C0) +#define DSI_PIXEL1_N REG_MM(0x4D0C4) +#define DSI_PIXEL1_D REG_MM(0x4D0C8) + +void platform_clock_init(void); + +void clock_init_mmc(uint32_t interface); +void clock_config_mmc(uint32_t interface, uint32_t freq); +void clock_config_uart_dm(uint8_t id); +void hsusb_clock_init(void); +void clock_config_ce(uint8_t instance); +void mdp_clock_init(void); +void mdp_gdsc_ctrl(uint8_t enable); +void clock_ce_enable(uint8_t instance); +void clock_ce_disable(uint8_t instance); +void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id); +#endif diff --git a/MSM8916Pkg/Include/Platform/iomap.h b/MSM8916Pkg/Include/Platform/iomap.h new file mode 100644 index 0000000..717e7e2 --- /dev/null +++ b/MSM8916Pkg/Include/Platform/iomap.h @@ -0,0 +1,286 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLATFORM_MSM8916_IOMAP_H_ +#define _PLATFORM_MSM8916_IOMAP_H_ + +#define MSM_IOMAP_BASE 0x00000000 +#define MSM_IOMAP_END 0x08000000 +#define A53_SS_BASE 0x0B000000 +#define A53_SS_END 0x0B200000 + +#define SYSTEM_IMEM_BASE 0x08600000 +#define MSM_SHARED_IMEM_BASE 0x08600000 + +#define RESTART_REASON_ADDR (MSM_SHARED_IMEM_BASE + 0x65C) +#define BS_INFO_OFFSET (0x6B0) +#define BS_INFO_ADDR (MSM_SHARED_IMEM_BASE + BS_INFO_OFFSET) +#define SDRAM_START_ADDR 0x80000000 + +#define MSM_SHARED_BASE 0x86300000 +#define APPS_SS_BASE 0x0B000000 + +#define DDR_START get_ddr_start() +#define ABOOT_FORCE_KERNEL_ADDR DDR_START + 0x8000 +#define ABOOT_FORCE_KERNEL64_ADDR DDR_START + 0x80000 +#define ABOOT_FORCE_RAMDISK_ADDR DDR_START + 0x2000000 +#define ABOOT_FORCE_TAGS_ADDR DDR_START + 0x1E00000 + +#define MSM_GIC_DIST_BASE APPS_SS_BASE +#define MSM_GIC_CPU_BASE (APPS_SS_BASE + 0x2000) +#define MSM_WATCHDOG_BASE (APPS_SS_BASE + 0x00017000) +#define MSM_WATCHDOG_RST (MSM_WATCHDOG_BASE + 0x04) +#define MSM_WATCHDOG_EN (MSM_WATCHDOG_BASE + 0x08) +#define APPS_APCS_QTMR_AC_BASE (APPS_SS_BASE + 0x00020000) +#define APPS_APCS_F0_QTMR_V1_BASE (APPS_SS_BASE + 0x00021000) +#define QTMR_BASE APPS_APCS_F0_QTMR_V1_BASE + +#define APCS_BANKED_SAW2_BASE (APPS_SS_BASE + 0x9000) +#define APCS_L2_SAW2_BASE (APPS_SS_BASE + 0x12000) + +#define PERIPH_SS_BASE 0x07800000 + +#define MSM_SDC1_BASE (PERIPH_SS_BASE + 0x00024000) +#define MSM_SDC1_SDHCI_BASE (PERIPH_SS_BASE + 0x00024900) +#define MSM_SDC2_BASE (PERIPH_SS_BASE + 0x00064000) +#define MSM_SDC2_SDHCI_BASE (PERIPH_SS_BASE + 0x00064900) + +/* SDHCI */ +#define SDCC_MCI_HC_MODE (0x00000078) +#define SDCC_HC_PWRCTL_STATUS_REG (0x000000DC) +#define SDCC_HC_PWRCTL_MASK_REG (0x000000E0) +#define SDCC_HC_PWRCTL_CLEAR_REG (0x000000E4) +#define SDCC_HC_PWRCTL_CTL_REG (0x000000E8) +#define BLSP1_UART0_BASE (PERIPH_SS_BASE + 0x000AF000) +#define BLSP1_UART1_BASE (PERIPH_SS_BASE + 0x000B0000) +#define MSM_USB_BASE (PERIPH_SS_BASE + 0x000D9000) + +#define CLK_CTL_BASE 0x1800000 + +#define SPMI_BASE 0x02000000 +#define SPMI_GENI_BASE (SPMI_BASE + 0xA000) +#define SPMI_PIC_BASE (SPMI_BASE + 0x01800000) +#define PMIC_ARB_CORE 0x200F000 + +#define TLMM_BASE_ADDR 0x1000000 +#define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + (x)*0x1000) +#define GPIO_IN_OUT_ADDR(x) (TLMM_BASE_ADDR + 0x00000004 + (x)*0x1000) + +#define MPM2_MPM_CTRL_BASE 0x004A0000 +#define MPM2_MPM_PS_HOLD 0x004AB000 +#define MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL 0x004A3000 + +/* CRYPTO ENGINE */ +#define MSM_CE1_BASE 0x073A000 +#define MSM_CE1_BAM_BASE 0x0704000 +#define GCC_CRYPTO_BCR (CLK_CTL_BASE + 0x16000) +#define GCC_CRYPTO_CMD_RCGR (CLK_CTL_BASE + 0x16004) +#define GCC_CRYPTO_CFG_RCGR (CLK_CTL_BASE + 0x16008) +#define GCC_CRYPTO_CBCR (CLK_CTL_BASE + 0x1601C) +#define GCC_CRYPTO_AXI_CBCR (CLK_CTL_BASE + 0x16020) +#define GCC_CRYPTO_AHB_CBCR (CLK_CTL_BASE + 0x16024) + +/* I2C */ +#define BLSP_QUP_BASE(blsp_id, qup_id) (PERIPH_SS_BASE + 0xB5000 + 0x1000 * qup_id) +#define GCC_BLSP1_QUP2_APPS_CBCR (CLK_CTL_BASE + 0x3010) +#define GCC_BLSP1_QUP2_CFG_RCGR (CLK_CTL_BASE + 0x3018) +#define GCC_BLSP1_QUP2_CMD_RCGR (CLK_CTL_BASE + 0x3014) + +/* GPLL */ +#define GPLL0_STATUS (CLK_CTL_BASE + 0x2101C) +#define GPLL1_STATUS (CLK_CTL_BASE + 0x2001C) +#define APCS_GPLL_ENA_VOTE (CLK_CTL_BASE + 0x45000) +#define APCS_CLOCK_BRANCH_ENA_VOTE (CLK_CTL_BASE + 0x45004) + +/* SDCC */ +#define SDC1_HDRV_PULL_CTL (TLMM_BASE_ADDR + 0x10A000) +#define SDCC1_BCR (CLK_CTL_BASE + 0x42000) /* block reset*/ +#define SDCC1_APPS_CBCR (CLK_CTL_BASE + 0x42018) /* branch ontrol */ +#define SDCC1_AHB_CBCR (CLK_CTL_BASE + 0x4201C) +#define SDCC1_CMD_RCGR (CLK_CTL_BASE + 0x42004) /* cmd */ +#define SDCC1_CFG_RCGR (CLK_CTL_BASE + 0x42008) /* cfg */ +#define SDCC1_M (CLK_CTL_BASE + 0x4200C) /* m */ +#define SDCC1_N (CLK_CTL_BASE + 0x42010) /* n */ +#define SDCC1_D (CLK_CTL_BASE + 0x42014) /* d */ + +#define SDC2_HDRV_PULL_CTL (TLMM_BASE_ADDR + 0x109000) +#define SDCC2_BCR (CLK_CTL_BASE + 0x43000) /* block reset */ +#define SDCC2_APPS_CBCR (CLK_CTL_BASE + 0x43018) /* branch control */ +#define SDCC2_AHB_CBCR (CLK_CTL_BASE + 0x4301C) +#define SDCC2_CMD_RCGR (CLK_CTL_BASE + 0x43004) /* cmd */ +#define SDCC2_CFG_RCGR (CLK_CTL_BASE + 0x43008) /* cfg */ +#define SDCC2_M (CLK_CTL_BASE + 0x4300C) /* m */ +#define SDCC2_N (CLK_CTL_BASE + 0x43010) /* n */ +#define SDCC2_D (CLK_CTL_BASE + 0x43014) /* d */ + +/* UART */ +#define BLSP1_AHB_CBCR (CLK_CTL_BASE + 0x1008) +#define BLSP1_UART1_APPS_CBCR (CLK_CTL_BASE + 0x203C) +#define BLSP1_UART1_APPS_CMD_RCGR (CLK_CTL_BASE + 0x2044) +#define BLSP1_UART1_APPS_CFG_RCGR (CLK_CTL_BASE + 0x2048) +#define BLSP1_UART1_APPS_M (CLK_CTL_BASE + 0x204C) +#define BLSP1_UART1_APPS_N (CLK_CTL_BASE + 0x2050) +#define BLSP1_UART1_APPS_D (CLK_CTL_BASE + 0x2054) +#define BLSP1_UART2_APPS_CBCR (CLK_CTL_BASE + 0x302C) +#define BLSP1_UART2_APPS_CMD_RCGR (CLK_CTL_BASE + 0x3034) +#define BLSP1_UART2_APPS_CFG_RCGR (CLK_CTL_BASE + 0x3038) +#define BLSP1_UART2_APPS_M (CLK_CTL_BASE + 0x303C) +#define BLSP1_UART2_APPS_N (CLK_CTL_BASE + 0x3040) +#define BLSP1_UART2_APPS_D (CLK_CTL_BASE + 0x3044) + + +/* USB */ +#define USB_HS_BCR (CLK_CTL_BASE + 0x41000) +#define USB_HS_SYSTEM_CBCR (CLK_CTL_BASE + 0x41004) +#define USB_HS_AHB_CBCR (CLK_CTL_BASE + 0x41008) +#define USB_HS_SYSTEM_CMD_RCGR (CLK_CTL_BASE + 0x41010) +#define USB_HS_SYSTEM_CFG_RCGR (CLK_CTL_BASE + 0x41014) + + +/* RPMB send receive buffer needs to be mapped + * as device memory, define the start address + * and size in MB + */ +#define RPMB_SND_RCV_BUF 0x90000000 +#define RPMB_SND_RCV_BUF_SZ 0x1 + +/* QSEECOM: Secure app region notification */ +#define APP_REGION_ADDR 0x86000000 +#define APP_REGION_SIZE 0x300000 + +/* MDSS */ +#define MIPI_DSI_BASE (0x1A98000) +#define MIPI_DSI0_BASE MIPI_DSI_BASE +#define MIPI_DSI1_BASE (0x1AA0000) +#define DSI0_PHY_BASE (0x1A98500) +#define DSI1_PHY_BASE (0x1AA0500) +#define DSI0_PLL_BASE (0x1A98300) +#define DSI1_PLL_BASE DSI0_PLL_BASE +#define REG_DSI(off) (MIPI_DSI_BASE + 0x04 + (off)) +#define MDP_BASE (0x1A00000) +#define REG_MDP(off) (MDP_BASE + (off)) +#define MDP_HW_REV REG_MDP(0x1000) +#define MDP_VP_0_VIG_0_BASE REG_MDP(0x5000) +#define MDP_VP_0_VIG_1_BASE REG_MDP(0x7000) +#define MDP_VP_0_RGB_0_BASE REG_MDP(0x15000) +#define MDP_VP_0_RGB_1_BASE REG_MDP(0x17000) +#define MDP_VP_0_DMA_0_BASE REG_MDP(0x25000) +#define MDP_VP_0_DMA_1_BASE REG_MDP(0x27000) +#define MDP_VP_0_MIXER_0_BASE REG_MDP(0x45000) +#define MDP_VP_0_MIXER_1_BASE REG_MDP(0x46000) +#define MDP_DISP_INTF_SEL REG_MDP(0x1004) +#define MDP_VIDEO_INTF_UNDERFLOW_CTL REG_MDP(0x12E0) +#define MDP_UPPER_NEW_ROI_PRIOR_RO_START REG_MDP(0x11EC) +#define MDP_LOWER_NEW_ROI_PRIOR_TO_START REG_MDP(0x13F8) +#define MDP_CTL_0_BASE REG_MDP(0x2000) +#define MDP_CTL_1_BASE REG_MDP(0x2200) +#define MDP_CLK_CTRL0 REG_MDP(0x012AC) +#define MDP_CLK_CTRL1 REG_MDP(0x012B4) +#define MDP_CLK_CTRL2 REG_MDP(0x012BC) +#define MDP_CLK_CTRL3 REG_MDP(0x013A8) +#define MDP_CLK_CTRL4 REG_MDP(0x013B0) +#define MDP_CLK_CTRL5 REG_MDP(0x013B8) + +#define MDP_INTF_0_BASE REG_MDP(0x11F00) +#define MDP_INTF_1_BASE REG_MDP(0x12700) +#define MDP_INTF_2_BASE REG_MDP(0x12F00) + +#define MDP_REG_SPLIT_DISPLAY_EN REG_MDP(0x12f4) +#define MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTL REG_MDP(0x12F8) +#define MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTL REG_MDP(0x13F0) + +#define MDP_REG_PPB0_CNTL REG_MDP(0x1420) +#define MDP_REG_PPB0_CONFIG REG_MDP(0x1424) + +#define MMSS_MDP_SMP_ALLOC_W_BASE REG_MDP(0x1080) +#define MMSS_MDP_SMP_ALLOC_R_BASE REG_MDP(0x1130) + +#define MDP_QOS_REMAPPER_CLASS_0 REG_MDP(0x11E0) + +#define VBIF_VBIF_DDR_FORCE_CLK_ON REG_MDP(0xc8004) +#define VBIF_VBIF_DDR_OUT_MAX_BURST REG_MDP(0xc80D8) +#define VBIF_VBIF_DDR_ARB_CTRL REG_MDP(0xc80F0) +#define VBIF_VBIF_DDR_RND_RBN_QOS_ARB REG_MDP(0xc8124) +#define VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0 REG_MDP(0xc8160) +#define VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1 REG_MDP(0xc8164) +#define VBIF_VBIF_DDR_OUT_AOOO_AXI_EN REG_MDP(0xc8178) +#define VBIF_VBIF_DDR_OUT_AX_AOOO REG_MDP(0xc817C) +#define VBIF_VBIF_IN_RD_LIM_CONF0 REG_MDP(0xc80B0) +#define VBIF_VBIF_IN_RD_LIM_CONF1 REG_MDP(0xc80B4) +#define VBIF_VBIF_IN_RD_LIM_CONF2 REG_MDP(0xc80B8) +#define VBIF_VBIF_IN_RD_LIM_CONF3 REG_MDP(0xc80BC) +#define VBIF_VBIF_IN_WR_LIM_CONF0 REG_MDP(0xc80C0) +#define VBIF_VBIF_IN_WR_LIM_CONF1 REG_MDP(0xc80C4) +#define VBIF_VBIF_IN_WR_LIM_CONF2 REG_MDP(0xc80C8) +#define VBIF_VBIF_IN_WR_LIM_CONF3 REG_MDP(0xc80CC) +#define VBIF_VBIF_ABIT_SHORT REG_MDP(0xc8070) +#define VBIF_VBIF_ABIT_SHORT_CONF REG_MDP(0xc8074) +#define VBIF_VBIF_GATE_OFF_WRREQ_EN REG_MDP(0xc80A8) + +#define SOFT_RESET 0x118 +#define CLK_CTRL 0x11C +#define TRIG_CTRL 0x084 +#define CTRL 0x004 +#define COMMAND_MODE_DMA_CTRL 0x03C +#define COMMAND_MODE_MDP_CTRL 0x040 +#define COMMAND_MODE_MDP_DCS_CMD_CTRL 0x044 +#define COMMAND_MODE_MDP_STREAM0_CTRL 0x058 +#define COMMAND_MODE_MDP_STREAM0_TOTAL 0x05C +#define COMMAND_MODE_MDP_STREAM1_CTRL 0x060 +#define COMMAND_MODE_MDP_STREAM1_TOTAL 0x064 +#define ERR_INT_MASK0 0x10C + +#define LANE_CTL 0x0AC +#define LANE_SWAP_CTL 0x0B0 +#define TIMING_CTL 0x0C4 + +#define VIDEO_MODE_ACTIVE_H 0x024 +#define VIDEO_MODE_ACTIVE_V 0x028 +#define VIDEO_MODE_TOTAL 0x02C +#define VIDEO_MODE_HSYNC 0x030 +#define VIDEO_MODE_VSYNC 0x034 +#define VIDEO_MODE_VSYNC_VPOS 0x038 + +#define DMA_CMD_OFFSET 0x048 +#define DMA_CMD_LENGTH 0x04C + +#define INT_CTRL 0x110 +#define CMD_MODE_DMA_SW_TRIGGER 0x090 + +#define EOT_PACKET_CTRL 0x0CC +#define MISR_CMD_CTRL 0x0A0 +#define MISR_VIDEO_CTRL 0x0A4 +#define VIDEO_MODE_CTRL 0x010 +#define HS_TIMER_CTRL 0x0BC + +#define TCSR_TZ_WONCE 0x193D000 +#define TCSR_BOOT_MISC_DETECT 0x193D100 + +#define BOOT_ROM_BASE 0x00100000 +#define BOOT_ROM_END 0x00124000 /* Crashes when reading more */ +#endif diff --git a/MSM8916Pkg/Include/Platform/irqs.h b/MSM8916Pkg/Include/Platform/irqs.h new file mode 100644 index 0000000..d85dd9a --- /dev/null +++ b/MSM8916Pkg/Include/Platform/irqs.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __IRQS_MSM8916_H +#define __IRQS_MSM8916_H + +/* MSM ACPU Interrupt Numbers */ + +/* 0-15: STI/SGI (software triggered/generated interrupts) + * 16-31: PPI (private peripheral interrupts) + * 32+: SPI (shared peripheral interrupts) + */ +int qtmr_irq(); + +#define GIC_PPI_START 16 +#define GIC_SPI_START 32 + +#define INT_QTMR_NON_SECURE_PHY_TIMER_EXP (GIC_PPI_START + 3) +#define INT_QTMR_VIRTUAL_TIMER_EXP (GIC_PPI_START + 4) + +#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP qtmr_irq() +#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP_8x16 (GIC_SPI_START + 8) +#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP_8x39 (GIC_SPI_START + 257) +#define SDCC1_PWRCTL_IRQ (GIC_SPI_START + 138) +#define SDCC2_PWRCTL_IRQ (GIC_SPI_START + 221) + +#define USB1_HS_BAM_IRQ (GIC_SPI_START + 135) +#define USB1_HS_IRQ (GIC_SPI_START + 134) + +/* Retrofit universal macro names */ +#define INT_USB_HS USB1_HS_IRQ + +#define EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ (GIC_SPI_START + 190) + +#define NR_MSM_IRQS 256 +#define NR_GPIO_IRQS 173 +#define NR_BOARD_IRQS 0 + +#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + \ + NR_BOARD_IRQS) + +#define BLSP_QUP_IRQ(blsp_id, qup_id) (GIC_SPI_START + 95 + qup_id) +#endif /* __IRQS_MSM8916_H */ diff --git a/MSM8916Pkg/Include/Protocol/QcomClock.h b/MSM8916Pkg/Include/Protocol/QcomClock.h new file mode 100644 index 0000000..14522b3 --- /dev/null +++ b/MSM8916Pkg/Include/Protocol/QcomClock.h @@ -0,0 +1,41 @@ +#ifndef __QCOM_PROTOCOL_CLOCK_H__ +#define __QCOM_PROTOCOL_CLOCK_H__ + +#include + +#define QCOM_CLOCK_PROTOCOL_GUID \ + { \ + 0x4fcc91c2, 0x9c4f, 0x4e3c, \ + { \ + 0xa6, 0x73, 0xc6, 0xdf, 0x62, 0xe0, 0x41, 0xd5 \ + } \ + } + +typedef struct _QCOM_CLOCK_PROTOCOL QCOM_CLOCK_PROTOCOL; + +typedef struct clk *(EFIAPI *clk_get_t)(const char *id); +typedef int(EFIAPI *clk_enable_t)(struct clk *clk); +typedef void(EFIAPI *clk_disable_t)(struct clk *clk); +typedef unsigned long(EFIAPI *clk_get_rate_t)(struct clk *clk); +typedef int(EFIAPI *clk_set_rate_t)(struct clk *clk, unsigned long rate); +typedef int(EFIAPI *clk_set_parent_t)(struct clk *clk, struct clk *parent); +typedef struct clk *(EFIAPI *clk_get_parent_t)(struct clk *clk); +typedef int(EFIAPI *clk_get_set_enable_t)( + char *id, unsigned long rate, bool enable); +typedef int(EFIAPI *clk_reset_t)(struct clk *clk, enum clk_reset_action); + +struct _QCOM_CLOCK_PROTOCOL { + clk_get_t clk_get; + clk_enable_t clk_enable; + clk_disable_t clk_disable; + clk_get_rate_t clk_get_rate; + clk_set_rate_t clk_set_rate; + clk_set_parent_t clk_set_parent; + clk_get_parent_t clk_get_parent; + clk_get_set_enable_t clk_get_set_enable; + clk_reset_t clk_reset; +}; + +extern EFI_GUID gQcomClockProtocolGuid; + +#endif diff --git a/MSM8916Pkg/Library/QcomPlatformClockInitLib/QcomPlatformClockInitLib.inf b/MSM8916Pkg/Library/QcomPlatformClockInitLib/QcomPlatformClockInitLib.inf new file mode 100644 index 0000000..b28552a --- /dev/null +++ b/MSM8916Pkg/Library/QcomPlatformClockInitLib/QcomPlatformClockInitLib.inf @@ -0,0 +1,24 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = QcomPlatformClockInitLib + FILE_GUID = 6B439EE9-31E2-4486-A95F-0AF5FAA31599 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = QcomPlatformClockInitLib + +[Sources] + msm8916-clock.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MSM8916Pkg/MSM8916Pkg.dec + +[LibraryClasses] + IoLib + ArmLib + +[BuildOptions.AARCH64] + GCC:*_*_*_CC_FLAGS = -Wno-pointer-to-int-cast -Wno-overflow -Wno-int-conversion + diff --git a/MSM8916Pkg/Library/QcomPlatformClockInitLib/msm8916-clock.c b/MSM8916Pkg/Library/QcomPlatformClockInitLib/msm8916-clock.c new file mode 100644 index 0000000..65841a9 --- /dev/null +++ b/MSM8916Pkg/Library/QcomPlatformClockInitLib/msm8916-clock.c @@ -0,0 +1,612 @@ +/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +/* Mux source select values */ +#define cxo_source_val 0 +#define gpll0_source_val 1 +#define cxo_mm_source_val 0 +#define gpll0_mm_source_val 5 +#define gpll1_mm_source_val 1 +struct clk_freq_tbl rcg_dummy_freq = F_END; + + +/* Clock Operations */ +static struct clk_ops clk_ops_branch = +{ + .enable = clock_lib2_branch_clk_enable, + .disable = clock_lib2_branch_clk_disable, + .set_rate = clock_lib2_branch_set_rate, +}; + +static struct clk_ops clk_ops_rcg_mnd = +{ + .enable = clock_lib2_rcg_enable, + .set_rate = clock_lib2_rcg_set_rate, +}; + +static struct clk_ops clk_ops_rcg = +{ + .enable = clock_lib2_rcg_enable, + .set_rate = clock_lib2_rcg_set_rate, +}; + +static struct clk_ops clk_ops_cxo = +{ + .enable = cxo_clk_enable, + .disable = cxo_clk_disable, +}; + +static struct clk_ops clk_ops_pll_vote = +{ + .enable = pll_vote_clk_enable, + .disable = pll_vote_clk_disable, + .auto_off = pll_vote_clk_disable, + .is_enabled = pll_vote_clk_is_enabled, +}; + +static struct clk_ops clk_ops_vote = +{ + .enable = clock_lib2_vote_clk_enable, + .disable = clock_lib2_vote_clk_disable, +}; + +/* Clock Sources */ +static struct fixed_clk cxo_clk_src = +{ + .c = { + .rate = 19200000, + .dbg_name = "cxo_clk_src", + .ops = &clk_ops_cxo, + }, +}; + +static struct pll_vote_clk gpll0_clk_src = +{ + .en_reg = (void *) APCS_GPLL_ENA_VOTE, + .en_mask = BIT(0), + .status_reg = (void *) GPLL0_STATUS, + .status_mask = BIT(17), + .parent = &cxo_clk_src.c, + + .c = { + .rate = 800000000, + .dbg_name = "gpll0_clk_src", + .ops = &clk_ops_pll_vote, + }, +}; + +/* SDCC Clocks */ +static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] = +{ + F( 144000, cxo, 16, 3, 25), + F( 400000, cxo, 12, 1, 4), + F( 20000000, gpll0, 10, 1, 4), + F( 25000000, gpll0, 16, 1, 2), + F( 50000000, gpll0, 16, 0, 0), + F(100000000, gpll0, 8, 0, 0), + F(177770000, gpll0, 4.5, 0, 0), + F(200000000, gpll0, 4, 0, 0), + F_END +}; + +static struct rcg_clk sdcc1_apps_clk_src = +{ + .cmd_reg = (uint32_t *) SDCC1_CMD_RCGR, + .cfg_reg = (uint32_t *) SDCC1_CFG_RCGR, + .m_reg = (uint32_t *) SDCC1_M, + .n_reg = (uint32_t *) SDCC1_N, + .d_reg = (uint32_t *) SDCC1_D, + + .set_rate = clock_lib2_rcg_set_rate_mnd, + .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "sdc1_clk", + .ops = &clk_ops_rcg_mnd, + }, +}; + +/* BLSP1_QUP2 Clocks */ +static struct clk_freq_tbl ftbl_gcc_blsp1_qup2_i2c_apps_clk_src[] = +{ + F( 96000, cxo, 10, 1, 2), + F( 4800000, cxo, 4, 0, 0), + F( 9600000, cxo, 2, 0, 0), + F( 16000000, gpll0, 10, 1, 5), + F( 19200000, gpll0, 1, 0, 0), + F( 25000000, gpll0, 16, 1, 2), + F( 50000000, gpll0, 16, 0, 0), + F_END +}; + +static struct branch_clk gcc_sdcc1_apps_clk = +{ + .cbcr_reg = (uint32_t *) SDCC1_APPS_CBCR, + .parent = &sdcc1_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_sdcc1_apps_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk gcc_sdcc1_ahb_clk = +{ + .cbcr_reg = (uint32_t *) SDCC1_AHB_CBCR, + .has_sibling = 1, + + .c = { + .dbg_name = "gcc_sdcc1_ahb_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct rcg_clk sdcc2_apps_clk_src = +{ + .cmd_reg = (uint32_t *) SDCC2_CMD_RCGR, + .cfg_reg = (uint32_t *) SDCC2_CFG_RCGR, + .m_reg = (uint32_t *) SDCC2_M, + .n_reg = (uint32_t *) SDCC2_N, + .d_reg = (uint32_t *) SDCC2_D, + + .set_rate = clock_lib2_rcg_set_rate_mnd, + .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "sdc2_clk", + .ops = &clk_ops_rcg_mnd, + }, +}; + +static struct branch_clk gcc_sdcc2_apps_clk = +{ + .cbcr_reg = (uint32_t *) SDCC2_APPS_CBCR, + .parent = &sdcc2_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_sdcc2_apps_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk gcc_sdcc2_ahb_clk = +{ + .cbcr_reg = (uint32_t *) SDCC2_AHB_CBCR, + .has_sibling = 1, + + .c = { + .dbg_name = "gcc_sdcc2_ahb_clk", + .ops = &clk_ops_branch, + }, +}; + +/* UART Clocks */ +static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = +{ + F( 3686400, gpll0, 1, 72, 15625), + F( 7372800, gpll0, 1, 144, 15625), + F(14745600, gpll0, 1, 288, 15625), + F(16000000, gpll0, 10, 1, 5), + F(19200000, cxo, 1, 0, 0), + F(24000000, gpll0, 1, 3, 100), + F(25000000, gpll0, 16, 1, 2), + F(32000000, gpll0, 1, 1, 25), + F(40000000, gpll0, 1, 1, 20), + F(46400000, gpll0, 1, 29, 500), + F(48000000, gpll0, 1, 3, 50), + F(51200000, gpll0, 1, 8, 125), + F(56000000, gpll0, 1, 7, 100), + F(58982400, gpll0, 1,1152, 15625), + F(60000000, gpll0, 1, 3, 40), + F_END +}; + +static struct rcg_clk blsp1_uart1_apps_clk_src = +{ + .cmd_reg = (uint32_t *) BLSP1_UART1_APPS_CMD_RCGR, + .cfg_reg = (uint32_t *) BLSP1_UART1_APPS_CFG_RCGR, + .m_reg = (uint32_t *) BLSP1_UART1_APPS_M, + .n_reg = (uint32_t *) BLSP1_UART1_APPS_N, + .d_reg = (uint32_t *) BLSP1_UART1_APPS_D, + + .set_rate = clock_lib2_rcg_set_rate_mnd, + .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "blsp1_uart1_apps_clk", + .ops = &clk_ops_rcg_mnd, + }, +}; + +static struct branch_clk gcc_blsp1_uart1_apps_clk = +{ + .cbcr_reg = (uint32_t *) BLSP1_UART1_APPS_CBCR, + .parent = &blsp1_uart1_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_blsp1_uart1_apps_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct rcg_clk blsp1_uart2_apps_clk_src = +{ + .cmd_reg = (uint32_t *) BLSP1_UART2_APPS_CMD_RCGR, + .cfg_reg = (uint32_t *) BLSP1_UART2_APPS_CFG_RCGR, + .m_reg = (uint32_t *) BLSP1_UART2_APPS_M, + .n_reg = (uint32_t *) BLSP1_UART2_APPS_N, + .d_reg = (uint32_t *) BLSP1_UART2_APPS_D, + + .set_rate = clock_lib2_rcg_set_rate_mnd, + .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "blsp1_uart2_apps_clk", + .ops = &clk_ops_rcg_mnd, + }, +}; + +static struct branch_clk gcc_blsp1_uart2_apps_clk = +{ + .cbcr_reg = (uint32_t *) BLSP1_UART2_APPS_CBCR, + .parent = &blsp1_uart2_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_blsp1_uart2_apps_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct vote_clk gcc_blsp1_ahb_clk = { + .cbcr_reg = (uint32_t *) BLSP1_AHB_CBCR, + .vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE, + .en_mask = BIT(10), + + .c = { + .dbg_name = "gcc_blsp1_ahb_clk", + .ops = &clk_ops_vote, + }, +}; + +/* USB Clocks */ +static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = +{ + F(80000000, gpll0, 10, 0, 0), + F_END +}; + +static struct rcg_clk usb_hs_system_clk_src = +{ + .cmd_reg = (uint32_t *) USB_HS_SYSTEM_CMD_RCGR, + .cfg_reg = (uint32_t *) USB_HS_SYSTEM_CFG_RCGR, + + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_gcc_usb_hs_system_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "usb_hs_system_clk", + .ops = &clk_ops_rcg, + }, +}; + +static struct branch_clk gcc_usb_hs_system_clk = +{ + .cbcr_reg = (uint32_t *) USB_HS_SYSTEM_CBCR, + .parent = &usb_hs_system_clk_src.c, + + .c = { + .dbg_name = "gcc_usb_hs_system_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk gcc_usb_hs_ahb_clk = +{ + .cbcr_reg = (uint32_t *) USB_HS_AHB_CBCR, + .has_sibling = 1, + + .c = { + .dbg_name = "gcc_usb_hs_ahb_clk", + .ops = &clk_ops_branch, + }, +}; + +/* Display clocks */ +static struct clk_freq_tbl ftbl_mdss_esc0_1_clk[] = { + F_MM(19200000, cxo, 1, 0, 0), + F_END +}; + +static struct clk_freq_tbl ftbl_mdss_esc1_1_clk[] = { + F_MM(19200000, cxo, 1, 0, 0), + F_END +}; + +static struct clk_freq_tbl ftbl_mdp_clk[] = { + F( 80000000, gpll0, 10, 0, 0), + F( 100000000, gpll0, 8, 0, 0), + F( 200000000, gpll0, 4, 0, 0), + F( 320000000, gpll0, 2.5, 0, 0), + F_END +}; + +static struct rcg_clk dsi_esc0_clk_src = { + .cmd_reg = (uint32_t *) DSI_ESC0_CMD_RCGR, + .cfg_reg = (uint32_t *) DSI_ESC0_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_mdss_esc0_1_clk, + + .c = { + .dbg_name = "dsi_esc0_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct rcg_clk dsi_esc1_clk_src = { + .cmd_reg = (uint32_t *) DSI_ESC1_CMD_RCGR, + .cfg_reg = (uint32_t *) DSI_ESC1_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_mdss_esc1_1_clk, + + .c = { + .dbg_name = "dsi_esc1_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct clk_freq_tbl ftbl_mdss_vsync_clk[] = { + F_MM(19200000, cxo, 1, 0, 0), + F_END +}; + +static struct rcg_clk vsync_clk_src = { + .cmd_reg = (uint32_t *) VSYNC_CMD_RCGR, + .cfg_reg = (uint32_t *) VSYNC_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_mdss_vsync_clk, + + .c = { + .dbg_name = "vsync_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct branch_clk mdss_esc0_clk = { + .cbcr_reg = (uint32_t *) DSI_ESC0_CBCR, + .parent = &dsi_esc0_clk_src.c, + .has_sibling = 0, + + .c = { + .dbg_name = "mdss_esc0_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk mdss_esc1_clk = { + .cbcr_reg = (uint32_t *) DSI_ESC1_CBCR, + .parent = &dsi_esc1_clk_src.c, + .has_sibling = 0, + + .c = { + .dbg_name = "mdss_esc1_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk mdss_axi_clk = { + .cbcr_reg = (uint32_t *) MDP_AXI_CBCR, + .has_sibling = 1, + + .c = { + .dbg_name = "mdss_axi_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk mdp_ahb_clk = { + .cbcr_reg = (uint32_t *) MDP_AHB_CBCR, + .has_sibling = 1, + + .c = { + .dbg_name = "mdp_ahb_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct rcg_clk mdss_mdp_clk_src = { + .cmd_reg = (uint32_t *) MDP_CMD_RCGR, + .cfg_reg = (uint32_t *) MDP_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_mdp_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "mdss_mdp_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct branch_clk mdss_mdp_clk = { + .cbcr_reg = (uint32_t *) MDP_CBCR, + .parent = &mdss_mdp_clk_src.c, + .has_sibling = 0, + + .c = { + .dbg_name = "mdss_mdp_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct branch_clk mdss_vsync_clk = { + .cbcr_reg = MDSS_VSYNC_CBCR, + .parent = &vsync_clk_src.c, + .has_sibling = 0, + + .c = { + .dbg_name = "mdss_vsync_clk", + .ops = &clk_ops_branch, + }, +}; + +static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = { + F(160000000, gpll0, 5, 0, 0), + F_END +}; + +static struct rcg_clk ce1_clk_src = { + .cmd_reg = (uint32_t *) GCC_CRYPTO_CMD_RCGR, + .cfg_reg = (uint32_t *) GCC_CRYPTO_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_gcc_ce1_clk, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "ce1_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct vote_clk gcc_ce1_clk = { + .cbcr_reg = (uint32_t *) GCC_CRYPTO_CBCR, + .vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE, + .en_mask = BIT(2), + + .c = { + .dbg_name = "gcc_ce1_clk", + .ops = &clk_ops_vote, + }, +}; + +static struct vote_clk gcc_ce1_ahb_clk = { + .cbcr_reg = (uint32_t *) GCC_CRYPTO_AHB_CBCR, + .vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE, + .en_mask = BIT(0), + + .c = { + .dbg_name = "gcc_ce1_ahb_clk", + .ops = &clk_ops_vote, + }, +}; + +static struct vote_clk gcc_ce1_axi_clk = { + .cbcr_reg = (uint32_t *) GCC_CRYPTO_AXI_CBCR, + .vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE, + .en_mask = BIT(1), + + .c = { + .dbg_name = "gcc_ce1_axi_clk", + .ops = &clk_ops_vote, + }, +}; + + +static struct rcg_clk gcc_blsp1_qup2_i2c_apps_clk_src = +{ + .cmd_reg = (uint32_t *) GCC_BLSP1_QUP2_CMD_RCGR, + .cfg_reg = (uint32_t *) GCC_BLSP1_QUP2_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_gcc_blsp1_qup2_i2c_apps_clk_src, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "gcc_blsp1_qup2_i2c_apps_clk_src", + .ops = &clk_ops_rcg, + }, +}; + +static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = { + .cbcr_reg = GCC_BLSP1_QUP2_APPS_CBCR, + .parent = &gcc_blsp1_qup2_i2c_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_blsp1_qup2_i2c_apps_clk", + .ops = &clk_ops_branch, + }, +}; +/* Clock lookup table */ +static struct clk_lookup msm_clocks_8916[] = +{ + CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c), + CLK_LOOKUP("sdc1_core_clk", gcc_sdcc1_apps_clk.c), + + CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c), + CLK_LOOKUP("sdc2_core_clk", gcc_sdcc2_apps_clk.c), + + CLK_LOOKUP("uart1_iface_clk", gcc_blsp1_ahb_clk.c), + CLK_LOOKUP("uart1_core_clk", gcc_blsp1_uart1_apps_clk.c), + + CLK_LOOKUP("uart2_iface_clk", gcc_blsp1_ahb_clk.c), + CLK_LOOKUP("uart2_core_clk", gcc_blsp1_uart2_apps_clk.c), + + CLK_LOOKUP("usb_iface_clk", gcc_usb_hs_ahb_clk.c), + CLK_LOOKUP("usb_core_clk", gcc_usb_hs_system_clk.c), + + CLK_LOOKUP("mdp_ahb_clk", mdp_ahb_clk.c), + CLK_LOOKUP("mdss_esc0_clk", mdss_esc0_clk.c), + CLK_LOOKUP("mdss_esc1_clk", mdss_esc1_clk.c), + CLK_LOOKUP("mdss_axi_clk", mdss_axi_clk.c), + CLK_LOOKUP("mdss_vsync_clk", mdss_vsync_clk.c), + CLK_LOOKUP("mdss_mdp_clk_src", mdss_mdp_clk_src.c), + CLK_LOOKUP("mdss_mdp_clk", mdss_mdp_clk.c), + + CLK_LOOKUP("ce1_ahb_clk", gcc_ce1_ahb_clk.c), + CLK_LOOKUP("ce1_axi_clk", gcc_ce1_axi_clk.c), + CLK_LOOKUP("ce1_core_clk", gcc_ce1_clk.c), + CLK_LOOKUP("ce1_src_clk", ce1_clk_src.c), + + CLK_LOOKUP("blsp1_qup2_ahb_iface_clk", gcc_blsp1_ahb_clk.c), + CLK_LOOKUP("gcc_blsp1_qup2_i2c_apps_clk_src", gcc_blsp1_qup2_i2c_apps_clk_src.c), + CLK_LOOKUP("gcc_blsp1_qup2_i2c_apps_clk", gcc_blsp1_qup2_i2c_apps_clk.c), +}; + +RETURN_STATUS +EFIAPI +LibQcomPlatformClockInit ( + struct clk_lookup **clist, + unsigned *num + ) +{ + + *clist = msm_clocks_8916; + *num = ARRAY_SIZE(msm_clocks_8916); + + return RETURN_SUCCESS; +} diff --git a/MSM8916Pkg/MSM8916Pkg.dec b/MSM8916Pkg/MSM8916Pkg.dec index daf5c0a..f87feff 100644 --- a/MSM8916Pkg/MSM8916Pkg.dec +++ b/MSM8916Pkg/MSM8916Pkg.dec @@ -33,6 +33,7 @@ [Protocols] gEFIDroidKeypadDeviceProtocolGuid = { 0xb27625b5, 0x0b6c, 0x4614, { 0xaa, 0x3c, 0x33, 0x13, 0xb5, 0x1d, 0x36, 0x46 } } + gQcomClockProtocolGuid = { 0x4fcc91c2, 0x9c4f, 0x4e3c, { 0xa6, 0x73, 0xc6, 0xdf, 0x62, 0xe0, 0x41, 0xd5 } } [PcdsFixedAtBuild.common] # Simple FrameBuffer diff --git a/MSM8916Pkg/MSM8916Pkg.dsc b/MSM8916Pkg/MSM8916Pkg.dsc index eb3c6c8..21f5064 100644 --- a/MSM8916Pkg/MSM8916Pkg.dsc +++ b/MSM8916Pkg/MSM8916Pkg.dsc @@ -72,6 +72,9 @@ MemoryInitPeiLib|MSM8916Pkg/Library/MemoryInitPeiLib/PeiMemoryAllocationLib.inf PlatformPeiLib|MSM8916Pkg/Library/PlatformPeiLib/PlatformPeiLib.inf + # SoC Drivers + QcomPlatformClockInitLib|MSM8916Pkg/Library/QcomPlatformClockInitLib/QcomPlatformClockInitLib.inf + [LibraryClasses.common.SEC] PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf @@ -79,6 +82,22 @@ MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf + # SoC Drivers + ClockLib|MSM8916Pkg/Drivers/ClockDxe/ClockImplLib.inf + +[LibraryClasses.common.DXE_DRIVER] + # SoC Drivers + ClockLib|MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + # SoC Drivers + ClockLib|MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + # SoC Drivers + ClockLib|MSM8916Pkg/Drivers/ClockDxe/ClockLib.inf + + ################################################################################ # # Pcd Section - list of all EDK II PCD Entries defined by this Platform @@ -180,9 +199,11 @@ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf # - # GPIO + # SoC Drivers # + MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf + # # Virtual Keyboard # diff --git a/MSM8916Pkg/MSM8916Pkg.fdf b/MSM8916Pkg/MSM8916Pkg.fdf index 37584c2..4053ee3 100644 --- a/MSM8916Pkg/MSM8916Pkg.fdf +++ b/MSM8916Pkg/MSM8916Pkg.fdf @@ -153,6 +153,10 @@ READ_LOCK_STATUS = TRUE INF MSM8916Pkg/Drivers/MSM8916PkgDxe/MSM8916PkgDxe.inf INF MSM8916Pkg/Drivers/SimpleFbDxe/SimpleFbDxe.inf + # + # SoC Drivers + # + INF MSM8916Pkg/Drivers/ClockDxe/ClockDxe.inf # # USB Host Support