Changes in 4.9.147 signal: Introduce COMPAT_SIGMINSTKSZ for use in compat_sys_sigaltstack lib/interval_tree_test.c: make test options module parameters lib/interval_tree_test.c: allow full tree search lib/rbtree_test.c: make input module parameters lib/rbtree-test: lower default params lib/interval_tree_test.c: allow users to limit scope of endpoint timer/debug: Change /proc/timer_list from 0444 to 0400 pinctrl: sunxi: a83t: Fix IRQ offset typo for PH11 aio: fix spectre gadget in lookup_ioctx MMC: OMAP: fix broken MMC on OMAP15XX/OMAP5910/OMAP310 ARM: mmp/mmp2: fix cpu_is_mmp2() on mmp2-dt tracing: Fix memory leak in set_trigger_filter() tracing: Fix memory leak of instance function hash filters powerpc/msi: Fix NULL pointer access in teardown code Revert "drm/rockchip: Allow driver to be shutdown on reboot/kexec" drm/i915/execlists: Apply a full mb before execution for Braswell mac80211: don't WARN on bad WMM parameters from buggy APs mac80211: Fix condition validating WMM IE IB/hfi1: Remove race conditions in user_sdma send path locking: Remove smp_read_barrier_depends() from queued_spin_lock_slowpath() locking/qspinlock: Ensure node is initialised before updating prev->next locking/qspinlock: Bound spinning on pending->locked transition in slowpath locking/qspinlock: Merge 'struct __qspinlock' into 'struct qspinlock' locking/qspinlock: Remove unbounded cmpxchg() loop from locking slowpath locking/qspinlock: Remove duplicate clear_pending() function from PV code locking/qspinlock: Kill cmpxchg() loop when claiming lock from head of queue locking/qspinlock: Re-order code locking/qspinlock/x86: Increase _Q_PENDING_LOOPS upper bound locking/qspinlock, x86: Provide liveness guarantee locking/qspinlock: Fix build for anonymous union in older GCC compilers mac80211_hwsim: fix module init error paths for netlink scsi: libiscsi: Fix NULL pointer dereference in iscsi_eh_session_reset scsi: vmw_pscsi: Rearrange code to avoid multiple calls to free_irq during unload x86/earlyprintk/efi: Fix infinite loop on some screen widths drm/msm: Grab a vblank reference when waiting for commit_done ARC: io.h: Implement reads{x}()/writes{x}() bonding: fix 802.3ad state sent to partner when unbinding slave nfs: don't dirty kernel pages read by direct-io SUNRPC: Fix a potential race in xprt_connect() sbus: char: add of_node_put() drivers/sbus/char: add of_node_put() drivers/tty: add missing of_node_put() ide: pmac: add of_node_put() clk: mvebu: Off by one bugs in cp110_of_clk_get() clk: mmp: Off by one in mmp_clk_add() Input: omap-keypad - fix keyboard debounce configuration libata: whitelist all SAMSUNG MZ7KM* solid-state disks mv88e6060: disable hardware level MAC learning net/mlx4_en: Fix build break when CONFIG_INET is off bpf: check pending signals while verifying programs ARM: 8814/1: mm: improve/fix ARM v7_dma_inv_range() unaligned address handling ARM: 8815/1: V7M: align v7m_dma_inv_range() with v7 counterpart ethernet: fman: fix wrong of_node_put() in probe function drm/ast: Fix connector leak during driver unload cifs: In Kconfig CONFIG_CIFS_POSIX needs depends on legacy (insecure cifs) vhost/vsock: fix reset orphans race with close timeout i2c: axxia: properly handle master timeout i2c: scmi: Fix probe error on devices with an empty SMB0001 ACPI device node nvmet-rdma: fix response use after free rtc: snvs: add a missing write sync rtc: snvs: Add timeouts to avoid kernel lockups Linux 4.9.147 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
192 lines
4.1 KiB
C
192 lines
4.1 KiB
C
#include <linux/io.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
|
|
#include "clk.h"
|
|
|
|
void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
|
|
int nr_clks)
|
|
{
|
|
static struct clk **clk_table;
|
|
|
|
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
|
|
if (!clk_table)
|
|
return;
|
|
|
|
unit->clk_table = clk_table;
|
|
unit->nr_clks = nr_clks;
|
|
unit->clk_data.clks = clk_table;
|
|
unit->clk_data.clk_num = nr_clks;
|
|
of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
|
|
}
|
|
|
|
void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_fixed_rate_clk *clks,
|
|
int size)
|
|
{
|
|
int i;
|
|
struct clk *clk;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = clk_register_fixed_rate(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].flags,
|
|
clks[i].fixed_rate);
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_fixed_factor_clk *clks,
|
|
int size)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = clk_register_fixed_factor(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].flags, clks[i].mult,
|
|
clks[i].div);
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_general_gate_clk *clks,
|
|
void __iomem *base, int size)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = clk_register_gate(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].flags,
|
|
base + clks[i].offset,
|
|
clks[i].bit_idx,
|
|
clks[i].gate_flags,
|
|
clks[i].lock);
|
|
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_register_gate_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_gate_clk *clks,
|
|
void __iomem *base, int size)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = mmp_clk_register_gate(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].flags,
|
|
base + clks[i].offset,
|
|
clks[i].mask,
|
|
clks[i].val_enable,
|
|
clks[i].val_disable,
|
|
clks[i].gate_flags,
|
|
clks[i].lock);
|
|
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_register_mux_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_mux_clk *clks,
|
|
void __iomem *base, int size)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = clk_register_mux(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].num_parents,
|
|
clks[i].flags,
|
|
base + clks[i].offset,
|
|
clks[i].shift,
|
|
clks[i].width,
|
|
clks[i].mux_flags,
|
|
clks[i].lock);
|
|
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_register_div_clks(struct mmp_clk_unit *unit,
|
|
struct mmp_param_div_clk *clks,
|
|
void __iomem *base, int size)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
clk = clk_register_divider(NULL, clks[i].name,
|
|
clks[i].parent_name,
|
|
clks[i].flags,
|
|
base + clks[i].offset,
|
|
clks[i].shift,
|
|
clks[i].width,
|
|
clks[i].div_flags,
|
|
clks[i].lock);
|
|
|
|
if (IS_ERR(clk)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, clks[i].name);
|
|
continue;
|
|
}
|
|
if (clks[i].id)
|
|
unit->clk_table[clks[i].id] = clk;
|
|
}
|
|
}
|
|
|
|
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
|
|
struct clk *clk)
|
|
{
|
|
if (IS_ERR_OR_NULL(clk)) {
|
|
pr_err("CLK %d has invalid pointer %p\n", id, clk);
|
|
return;
|
|
}
|
|
if (id >= unit->nr_clks) {
|
|
pr_err("CLK %d is invalid\n", id);
|
|
return;
|
|
}
|
|
|
|
unit->clk_table[id] = clk;
|
|
}
|