Need to control phy's digital block before enabling pll and
waiting for it into locked state.
Change-Id: I04037f5496fd5c1ef4e24853eb32b43ce326ff01
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
*/
#include <linux/delay.h>
*/
#include <linux/delay.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#define GRF_EMMCPHY_CON5 0x14
#define GRF_EMMCPHY_CON6 0x18
#define GRF_EMMCPHY_STATUS 0x20
#define GRF_EMMCPHY_CON5 0x14
#define GRF_EMMCPHY_CON6 0x18
#define GRF_EMMCPHY_STATUS 0x20
+#define CTRL_OFFSET 0x2c
+#define CTRL_INTER_CLKEN 0x1
+#define CTRL_INTER_CLKRDY 0x1
+#define CTRL_INTER_CLKOUT 0x1
#define PHYCTRL_PDB_MASK 0x1
#define PHYCTRL_PDB_SHIFT 0x0
#define PHYCTRL_PDB_PWR_ON 0x1
#define PHYCTRL_PDB_MASK 0x1
#define PHYCTRL_PDB_SHIFT 0x0
#define PHYCTRL_PDB_PWR_ON 0x1
struct rockchip_emmc_phy {
unsigned int reg_offset;
struct regmap *reg_base;
struct rockchip_emmc_phy {
unsigned int reg_offset;
struct regmap *reg_base;
+ void __iomem *ctrl_base;
u32 freq_sel;
u32 dr_sel;
u32 opdelay;
u32 freq_sel;
u32 dr_sel;
u32 opdelay;
{
unsigned int caldone;
unsigned int dllrdy;
{
unsigned int caldone;
unsigned int dllrdy;
+ u16 ctrl_val;
+ unsigned long timeout;
/*
* Keep phyctrl_pdb and phyctrl_endll low to allow
/*
* Keep phyctrl_pdb and phyctrl_endll low to allow
if (on_off == PHYCTRL_PDB_PWR_OFF)
return 0;
if (on_off == PHYCTRL_PDB_PWR_OFF)
return 0;
+ ctrl_val = readw(rk_phy->ctrl_base + CTRL_OFFSET);
+ ctrl_val |= CTRL_INTER_CLKEN;
+ writew(ctrl_val, rk_phy->ctrl_base + CTRL_OFFSET);
+ /* Wait max 20 ms */
+ while (!((ctrl_val = readw(rk_phy->ctrl_base + CTRL_OFFSET))
+ & CTRL_INTER_CLKRDY)) {
+ if (timeout == 0) {
+ pr_err("rockchip_emmc_phy_power_on: inter_clk not rdy\n");
+ return -EINVAL;
+ }
+ timeout--;
+ mdelay(1);
+ }
+ ctrl_val |= CTRL_INTER_CLKOUT;
+ writew(ctrl_val, rk_phy->ctrl_base + CTRL_OFFSET);
+
/*
* According to the user manual, calpad calibration
* cycle takes more than 2us without the minimal recommended
/*
* According to the user manual, calpad calibration
* cycle takes more than 2us without the minimal recommended
u32 freq_sel;
u32 dr_sel;
u32 opdelay;
u32 freq_sel;
u32 dr_sel;
u32 opdelay;
grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
if (IS_ERR(grf)) {
grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
if (IS_ERR(grf)) {
+ if (of_property_read_u32(dev->of_node, "ctrl-base", &ctrl_base)) {
+ dev_err(dev, "missing ctrl-base property in node %s\n",
+ dev->of_node->name);
+ return -EINVAL;
+ }
+
+ rk_phy->ctrl_base = ioremap(ctrl_base, SZ_1K);
+ if (!rk_phy->ctrl_base) {
+ dev_err(dev, "failed to remap ctrl_base!\n");
+ return -ENOMEM;
+ }
+
rk_phy->freq_sel = 0x0;
if (!of_property_read_u32(dev->of_node, "freq-sel", &freq_sel)) {
switch (freq_sel) {
rk_phy->freq_sel = 0x0;
if (!of_property_read_u32(dev->of_node, "freq-sel", &freq_sel)) {
switch (freq_sel) {
generic_phy = devm_phy_create(dev, dev->of_node, &ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
generic_phy = devm_phy_create(dev, dev->of_node, &ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
+ iounmap(rk_phy->ctrl_base);
return PTR_ERR(generic_phy);
}
return PTR_ERR(generic_phy);
}