Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc857387 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: 8092: add clocks supplied by vcap"

parents 935bb63e d3ebd956
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ obj-$(CONFIG_ARCH_MDM9630) += board-9630.o board-9630-gpiomux.o
obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
obj-$(CONFIG_ARCH_MSMSAMARIUM) += clock-local2.o clock-pll.o clock-rpm.o clock-samarium.o clock-krait-8974.o clock-mdss-8974.o
obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
obj-$(CONFIG_ARCH_MPQ8092) += clock-local2.o clock-pll.o clock-rpm.o clock-voter.o clock-8092.o
obj-$(CONFIG_ARCH_MPQ8092) += clock-local2.o clock-pll.o clock-rpm.o clock-voter.o clock-8092.o clock-vcap-8092.o
obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8974.o
obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
+185 −0
Original line number Diff line number Diff line
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#define pr_fmt(fmt)	"VCAP_CLK, %s: " fmt, __func__

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/iopoll.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/clk/msm-clk-provider.h>
#include <linux/clk/msm-clk.h>
#include <linux/clk/msm-clock-generic.h>

#include "clock-vcap-8092.h"

#define VCAP_MISC_REG_BASE	0xfdf81000
#define VCAP_MISC_REG_SIZE	0x1000

#define VCAP_GDSC_PHYS		0xfd8c1800
#define VCAP_GDSC_SIZE		8

#define VCAP_MISC_AAFE_CTRL_5	0x0018
#define VCAP_MISC_SPARE_RW	0x0350

/* lock to serialize access to VCAP misc registers */
spinlock_t vcap_mis_reg_lock;

static unsigned char *vcap_mis_reg_base;
static unsigned char *vcap_gdsc_base;
static struct clk *vcap_ahb_clk;
static struct clk *vcap_vp_clk;

/*
 * The following three register access functions are also used
 * by VCAP driver:
 *    vcap_misc_reg_read
 *    vcap_misc_reg_write
 *    vcap_misc_reg_w_bits
 */
int vcap_misc_reg_read(u32 offset, u32 *rd_val)
{
	if (!vcap_mis_reg_base)
		return -ENODEV;

	if ((offset & 3) || (offset >= VCAP_MISC_REG_SIZE))
		return -EINVAL;

	*rd_val = readl_relaxed(vcap_mis_reg_base + offset);

	return 0;
}
EXPORT_SYMBOL(vcap_misc_reg_read);

int vcap_misc_reg_write(u32 offset, u32 wr_val)
{
	if (!vcap_mis_reg_base)
		return -ENODEV;

	if ((offset & 3) || (offset >= VCAP_MISC_REG_SIZE))
		return -EINVAL;

	writel_relaxed(wr_val, vcap_mis_reg_base + offset);

	return 0;
}
EXPORT_SYMBOL(vcap_misc_reg_write);

int vcap_misc_reg_w_bits(u32 offset, u32 bits, u32 mask)
{
	unsigned long flags = 0;
	u32 temp = 0;

	if (!vcap_mis_reg_base)
		return -ENODEV;

	if ((offset & 3) || (offset >= VCAP_MISC_REG_SIZE))
		return -EINVAL;

	spin_lock_irqsave(&vcap_mis_reg_lock, flags);
	temp = readl_relaxed(vcap_mis_reg_base + offset);
	temp &= ~mask;
	temp |= (bits & mask);
	writel_relaxed(temp, vcap_mis_reg_base + offset);
	spin_unlock_irqrestore(&vcap_mis_reg_lock, flags);

	return 0;
}
EXPORT_SYMBOL(vcap_misc_reg_w_bits);

static int afe_pixel_clk_enable(struct clk *clk)
{
	vcap_misc_reg_w_bits(VCAP_MISC_AAFE_CTRL_5, 1, 1);

	return 0;
}

static void afe_pixel_clk_disable(struct clk *clk)
{
	vcap_misc_reg_w_bits(VCAP_MISC_AAFE_CTRL_5, 0, 1);
}

static struct clk_ops afe_pixel_clk_ops = {
	.enable = afe_pixel_clk_enable,
	.disable = afe_pixel_clk_disable,
};

static unsigned long hdmirx_tmds_clk_get_rate(struct clk *clk)
{
	u32 temp, rc;
	u32 rate = 0;

	/*
	 * before this fucntion is triggered, VCAP driver should
	 * write a magic value into this spare register. This value
	 * will be the CTS received by HDMI when audio is available,
	 * and a pre defined value when HDMI audio is not present.
	 * This value will be used if set_rate has to be called for
	 * the two clocks derived from TMDS: hdmi_rx_clk and hdmi_bus_clk
	 *
	 * The N value from ACR is used for set_rate on aud_clk
	 */
	rc = vcap_misc_reg_read(VCAP_MISC_SPARE_RW, &temp);
	if (!rc)
		rate = temp & 0x3fffffff;
	else
		pr_warn("read CTS from spare register fails\n");

	return rate;
}

static struct clk_ops clk_ops_tmds_clk = {
	.get_rate = hdmirx_tmds_clk_get_rate,
};

struct afe_pixel_clk vcap_afe_pixel_clk_src = {
	.c = {
		.dbg_name = "vcap_afe_pixel_clk_src",
		.ops = &afe_pixel_clk_ops,
		CLK_INIT(vcap_afe_pixel_clk_src.c),
	}
};

struct hdmirx_tmds_clk vcap_tmds_clk_src = {
	.c = {
		.dbg_name = "vcap_tmds_clk",
		.ops = &clk_ops_tmds_clk,
		CLK_INIT(vcap_tmds_clk_src.c),
	},
};

/* to be called by 8092_clock_pre_init */
void vcap_clk_ctrl_pre_init(struct clk *ahb_clk, struct clk *vp_clk)
{
	BUG_ON(ahb_clk == NULL || vp_clk == NULL);

	vcap_ahb_clk = ahb_clk;
	vcap_vp_clk = vp_clk;

	spin_lock_init(&vcap_mis_reg_lock);

	vcap_gdsc_base = ioremap_nocache(VCAP_GDSC_PHYS, VCAP_GDSC_SIZE);
	if (!vcap_gdsc_base)
		pr_err("%s: fail to map vcap gdsc\n",  __func__);

	vcap_mis_reg_base =
		ioremap_nocache(VCAP_MISC_REG_BASE, VCAP_MISC_REG_SIZE);
	if (!vcap_mis_reg_base) {
		pr_err("%s: fail to map vcap misc reg\n",  __func__);
		iounmap(vcap_gdsc_base);
	}
}
+32 −0
Original line number Diff line number Diff line
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef __CLK_VCAP_8092_H__
#define __CLK_VCAP_8092_H__

#include <linux/clk.h>

void vcap_clk_ctrl_pre_init(struct clk *ahb_clk, struct clk *vp_clk);

struct hdmirx_tmds_clk {
	struct clk c;
};

struct afe_pixel_clk {
	struct clk c;
};

extern struct hdmirx_tmds_clk vcap_tmds_clk_src;
extern struct afe_pixel_clk vcap_afe_pixel_clk_src;

#endif /* __CLK_VCAP_8092_H__ */