Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
fb441329
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
fb441329
编写于
1月 24, 2018
作者:
T
Tom Rini
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.denx.de/u-boot-mmc
上级
16121280
2f516e4a
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
836 addition
and
33 deletion
+836
-33
configs/odroid-xu3_defconfig
configs/odroid-xu3_defconfig
+2
-0
drivers/core/read.c
drivers/core/read.c
+5
-0
drivers/mmc/Kconfig
drivers/mmc/Kconfig
+5
-0
drivers/mmc/fsl_esdhc.c
drivers/mmc/fsl_esdhc.c
+6
-1
drivers/mmc/mmc-uclass.c
drivers/mmc/mmc-uclass.c
+4
-5
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+11
-5
drivers/mmc/sdhci-cadence.c
drivers/mmc/sdhci-cadence.c
+95
-19
drivers/mmc/sdhci.c
drivers/mmc/sdhci.c
+3
-3
drivers/power/pmic/s2mps11.c
drivers/power/pmic/s2mps11.c
+28
-0
drivers/power/regulator/Kconfig
drivers/power/regulator/Kconfig
+8
-0
drivers/power/regulator/Makefile
drivers/power/regulator/Makefile
+1
-0
drivers/power/regulator/s2mps11_regulator.c
drivers/power/regulator/s2mps11_regulator.c
+597
-0
include/dm/read.h
include/dm/read.h
+16
-0
include/power/s2mps11.h
include/power/s2mps11.h
+55
-0
未找到文件。
configs/odroid-xu3_defconfig
浏览文件 @
fb441329
...
...
@@ -22,6 +22,7 @@ CONFIG_CMD_CACHE=y
CONFIG_CMD_TIME=y
CONFIG_CMD_PMIC=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_REGULATOR=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ADC=y
CONFIG_ADC_EXYNOS=y
...
...
@@ -35,6 +36,7 @@ CONFIG_SMC911X_BASE=0x5000000
CONFIG_DM_PMIC=y
CONFIG_PMIC_S2MPS11=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_S2MPS11=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_XHCI_HCD=y
...
...
drivers/core/read.c
浏览文件 @
fb441329
...
...
@@ -10,6 +10,11 @@
#include <mapmem.h>
#include <dm/of_access.h>
int
dev_read_u32
(
struct
udevice
*
dev
,
const
char
*
propname
,
u32
*
outp
)
{
return
ofnode_read_u32
(
dev_ofnode
(
dev
),
propname
,
outp
);
}
int
dev_read_u32_default
(
struct
udevice
*
dev
,
const
char
*
propname
,
int
def
)
{
return
ofnode_read_u32_default
(
dev_ofnode
(
dev
),
propname
,
def
);
...
...
drivers/mmc/Kconfig
浏览文件 @
fb441329
...
...
@@ -17,6 +17,11 @@ config MMC_WRITE
help
Enable write access to MMC and SD Cards
config MMC_BROKEN_CD
bool "Poll for broken card detection case"
help
If card detection feature is broken, just poll to detect.
config DM_MMC
bool "Enable MMC controllers using Driver Model"
depends on DM
...
...
drivers/mmc/fsl_esdhc.c
浏览文件 @
fb441329
...
...
@@ -528,14 +528,19 @@ out:
static
void
set_sysctl
(
struct
fsl_esdhc_priv
*
priv
,
struct
mmc
*
mmc
,
uint
clock
)
{
struct
fsl_esdhc
*
regs
=
priv
->
esdhc_regs
;
int
div
=
1
;
#ifdef ARCH_MXC
#ifdef CONFIG_MX53
/* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */
int
pre_div
=
(
regs
==
(
struct
fsl_esdhc
*
)
MMC_SDHC3_BASE_ADDR
)
?
2
:
1
;
#else
int
pre_div
=
1
;
#endif
#else
int
pre_div
=
2
;
#endif
int
ddr_pre_div
=
mmc
->
ddr_mode
?
2
:
1
;
struct
fsl_esdhc
*
regs
=
priv
->
esdhc_regs
;
int
sdhc_clk
=
priv
->
sdhc_clk
;
uint
clk
;
...
...
drivers/mmc/mmc-uclass.c
浏览文件 @
fb441329
...
...
@@ -140,13 +140,12 @@ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
cfg
->
host_caps
|=
MMC_MODE_1BIT
;
break
;
default:
debug
(
"warning: %s invalid bus-width property. using 1-bit
\n
"
,
dev_read_name
(
dev
));
cfg
->
host_caps
|=
MMC_MODE_1BIT
;
break
;
dev_err
(
dev
,
"Invalid
\"
bus-width
\"
value %u!
\n
"
,
val
);
return
-
EINVAL
;
}
cfg
->
f_max
=
dev_read_u32_default
(
dev
,
"max-frequency"
,
52000000
);
/* f_max is obtained from the optional "max-frequency" property */
dev_read_u32
(
dev
,
"max-frequency"
,
&
cfg
->
f_max
);
if
(
dev_read_bool
(
dev
,
"cap-sd-highspeed"
))
cfg
->
host_caps
|=
MMC_CAP
(
SD_HS
);
...
...
drivers/mmc/mmc.c
浏览文件 @
fb441329
...
...
@@ -1501,11 +1501,13 @@ static int mmc_set_ios(struct mmc *mmc)
int
mmc_set_clock
(
struct
mmc
*
mmc
,
uint
clock
,
bool
disable
)
{
if
(
clock
>
mmc
->
cfg
->
f_max
)
clock
=
mmc
->
cfg
->
f_max
;
if
(
!
disable
)
{
if
(
clock
>
mmc
->
cfg
->
f_max
)
clock
=
mmc
->
cfg
->
f_max
;
if
(
clock
<
mmc
->
cfg
->
f_min
)
clock
=
mmc
->
cfg
->
f_min
;
if
(
clock
<
mmc
->
cfg
->
f_min
)
clock
=
mmc
->
cfg
->
f_min
;
}
mmc
->
clock
=
clock
;
mmc
->
clk_disable
=
disable
;
...
...
@@ -2449,7 +2451,7 @@ static int mmc_power_on(struct mmc *mmc)
static
int
mmc_power_off
(
struct
mmc
*
mmc
)
{
mmc_set_clock
(
mmc
,
1
,
true
);
mmc_set_clock
(
mmc
,
0
,
true
);
#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
if
(
mmc
->
vmmc_supply
)
{
int
ret
=
regulator_set_enable
(
mmc
->
vmmc_supply
,
false
);
...
...
@@ -2491,8 +2493,12 @@ int mmc_start_init(struct mmc *mmc)
mmc
->
host_caps
=
mmc
->
cfg
->
host_caps
|
MMC_CAP
(
SD_LEGACY
)
|
MMC_CAP
(
MMC_LEGACY
)
|
MMC_MODE_1BIT
;
#if !defined(CONFIG_MMC_BROKEN_CD)
/* we pretend there's no card when init is NULL */
no_card
=
mmc_getcd
(
mmc
)
==
0
;
#else
no_card
=
0
;
#endif
#if !CONFIG_IS_ENABLED(DM_MMC)
no_card
=
no_card
||
(
mmc
->
cfg
->
ops
->
init
==
NULL
);
#endif
...
...
drivers/mmc/sdhci-cadence.c
浏览文件 @
fb441329
...
...
@@ -7,6 +7,7 @@
#include <common.h>
#include <dm.h>
#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/sizes.h>
...
...
@@ -19,15 +20,14 @@
#define SDHCI_CDNS_HRS04_ACK BIT(26)
#define SDHCI_CDNS_HRS04_RD BIT(25)
#define SDHCI_CDNS_HRS04_WR BIT(24)
#define SDHCI_CDNS_HRS04_RDATA
_SHIFT 16
#define SDHCI_CDNS_HRS04_WDATA
_SHIFT 8
#define SDHCI_CDNS_HRS04_ADDR
_SHIFT 0
#define SDHCI_CDNS_HRS04_RDATA
GENMASK(23, 16)
#define SDHCI_CDNS_HRS04_WDATA
GENMASK(15, 8)
#define SDHCI_CDNS_HRS04_ADDR
GENMASK(5, 0)
#define SDHCI_CDNS_HRS06 0x18
/* eMMC control */
#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15)
#define SDHCI_CDNS_HRS06_TUNE_SHIFT 8
#define SDHCI_CDNS_HRS06_TUNE_MASK 0x3f
#define SDHCI_CDNS_HRS06_MODE_MASK 0x7
#define SDHCI_CDNS_HRS06_TUNE GENMASK(13, 8)
#define SDHCI_CDNS_HRS06_MODE GENMASK(2, 0)
#define SDHCI_CDNS_HRS06_MODE_SD 0x0
#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2
#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3
...
...
@@ -52,6 +52,13 @@
#define SDHCI_CDNS_PHY_DLY_HSMMC 0x0c
#define SDHCI_CDNS_PHY_DLY_STROBE 0x0d
/*
* The tuned val register is 6 bit-wide, but not the whole of the range is
* available. The range 0-42 seems to be available (then 43 wraps around to 0)
* but I am not quite sure if it is official. Use only 0 to 39 for safety.
*/
#define SDHCI_CDNS_MAX_TUNING_LOOP 40
struct
sdhci_cdns_plat
{
struct
mmc_config
cfg
;
struct
mmc
mmc
;
...
...
@@ -84,8 +91,8 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_plat *plat,
u32
tmp
;
int
ret
;
tmp
=
(
data
<<
SDHCI_CDNS_HRS04_WDATA_SHIFT
)
|
(
addr
<<
SDHCI_CDNS_HRS04_ADDR_SHIFT
);
tmp
=
FIELD_PREP
(
SDHCI_CDNS_HRS04_WDATA
,
data
)
|
FIELD_PREP
(
SDHCI_CDNS_HRS04_ADDR
,
addr
);
writel
(
tmp
,
reg
);
tmp
|=
SDHCI_CDNS_HRS04_WR
;
...
...
@@ -135,25 +142,23 @@ static void sdhci_cdns_set_control_reg(struct sdhci_host *host)
* The mode should be decided by MMC_TIMING_* like Linux, but
* U-Boot does not support timing. Use the clock frequency instead.
*/
if
(
clock
<=
26000000
)
if
(
clock
<=
26000000
)
{
mode
=
SDHCI_CDNS_HRS06_MODE_SD
;
/* use this for Legacy */
else
if
(
clock
<=
52000000
)
{
}
else
if
(
clock
<=
52000000
)
{
if
(
mmc
->
ddr_mode
)
mode
=
SDHCI_CDNS_HRS06_MODE_MMC_DDR
;
else
mode
=
SDHCI_CDNS_HRS06_MODE_MMC_SDR
;
}
else
{
/*
* REVISIT:
* The IP supports HS200/HS400, revisit once U-Boot support it
*/
printf
(
"unsupported frequency %d
\n
"
,
clock
);
return
;
if
(
mmc
->
ddr_mode
)
mode
=
SDHCI_CDNS_HRS06_MODE_MMC_HS400
;
else
mode
=
SDHCI_CDNS_HRS06_MODE_MMC_HS200
;
}
tmp
=
readl
(
plat
->
hrs_addr
+
SDHCI_CDNS_HRS06
);
tmp
&=
~
SDHCI_CDNS_HRS06_MODE
_MASK
;
tmp
|=
mode
;
tmp
&=
~
SDHCI_CDNS_HRS06_MODE
;
tmp
|=
FIELD_PREP
(
SDHCI_CDNS_HRS06_MODE
,
mode
)
;
writel
(
tmp
,
plat
->
hrs_addr
+
SDHCI_CDNS_HRS06
);
}
...
...
@@ -161,6 +166,69 @@ static const struct sdhci_ops sdhci_cdns_ops = {
.
set_control_reg
=
sdhci_cdns_set_control_reg
,
};
static
int
sdhci_cdns_set_tune_val
(
struct
sdhci_cdns_plat
*
plat
,
unsigned
int
val
)
{
void
__iomem
*
reg
=
plat
->
hrs_addr
+
SDHCI_CDNS_HRS06
;
u32
tmp
;
if
(
WARN_ON
(
!
FIELD_FIT
(
SDHCI_CDNS_HRS06_TUNE
,
val
)))
return
-
EINVAL
;
tmp
=
readl
(
reg
);
tmp
&=
~
SDHCI_CDNS_HRS06_TUNE
;
tmp
|=
FIELD_PREP
(
SDHCI_CDNS_HRS06_TUNE
,
val
);
tmp
|=
SDHCI_CDNS_HRS06_TUNE_UP
;
writel
(
tmp
,
reg
);
return
readl_poll_timeout
(
reg
,
tmp
,
!
(
tmp
&
SDHCI_CDNS_HRS06_TUNE_UP
),
1
);
}
static
int
__maybe_unused
sdhci_cdns_execute_tuning
(
struct
udevice
*
dev
,
unsigned
int
opcode
)
{
struct
sdhci_cdns_plat
*
plat
=
dev_get_platdata
(
dev
);
struct
mmc
*
mmc
=
&
plat
->
mmc
;
int
cur_streak
=
0
;
int
max_streak
=
0
;
int
end_of_streak
=
0
;
int
i
;
/*
* This handler only implements the eMMC tuning that is specific to
* this controller. The tuning for SD timing should be handled by the
* SDHCI core.
*/
if
(
!
IS_MMC
(
mmc
))
return
-
ENOTSUPP
;
if
(
WARN_ON
(
opcode
!=
MMC_CMD_SEND_TUNING_BLOCK_HS200
))
return
-
EINVAL
;
for
(
i
=
0
;
i
<
SDHCI_CDNS_MAX_TUNING_LOOP
;
i
++
)
{
if
(
sdhci_cdns_set_tune_val
(
plat
,
i
)
||
mmc_send_tuning
(
mmc
,
opcode
,
NULL
))
{
/* bad */
cur_streak
=
0
;
}
else
{
/* good */
cur_streak
++
;
if
(
cur_streak
>
max_streak
)
{
max_streak
=
cur_streak
;
end_of_streak
=
i
;
}
}
}
if
(
!
max_streak
)
{
dev_err
(
dev
,
"no tuning point found
\n
"
);
return
-
EIO
;
}
return
sdhci_cdns_set_tune_val
(
plat
,
end_of_streak
-
max_streak
/
2
);
}
static
struct
dm_mmc_ops
sdhci_cdns_mmc_ops
;
static
int
sdhci_cdns_bind
(
struct
udevice
*
dev
)
{
struct
sdhci_cdns_plat
*
plat
=
dev_get_platdata
(
dev
);
...
...
@@ -189,6 +257,14 @@ static int sdhci_cdns_probe(struct udevice *dev)
host
->
ioaddr
=
plat
->
hrs_addr
+
SDHCI_CDNS_SRS_BASE
;
host
->
ops
=
&
sdhci_cdns_ops
;
host
->
quirks
|=
SDHCI_QUIRK_WAIT_SEND_CMD
;
sdhci_cdns_mmc_ops
=
sdhci_ops
;
#ifdef MMC_SUPPORTS_TUNING
sdhci_cdns_mmc_ops
.
execute_tuning
=
sdhci_cdns_execute_tuning
;
#endif
ret
=
mmc_of_parse
(
dev
,
&
plat
->
cfg
);
if
(
ret
)
return
ret
;
ret
=
sdhci_cdns_phy_init
(
plat
,
gd
->
fdt_blob
,
dev_of_offset
(
dev
));
if
(
ret
)
...
...
@@ -219,5 +295,5 @@ U_BOOT_DRIVER(sdhci_cdns) = {
.
probe
=
sdhci_cdns_probe
,
.
priv_auto_alloc_size
=
sizeof
(
struct
sdhci_host
),
.
platdata_auto_alloc_size
=
sizeof
(
struct
sdhci_cdns_plat
),
.
ops
=
&
sdhci_ops
,
.
ops
=
&
sdhci_
cdns_mmc_
ops
,
};
drivers/mmc/sdhci.c
浏览文件 @
fb441329
...
...
@@ -86,8 +86,8 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
do
{
stat
=
sdhci_readl
(
host
,
SDHCI_INT_STATUS
);
if
(
stat
&
SDHCI_INT_ERROR
)
{
pr
intf
(
"%s: Error detected in status(0x%X)!
\n
"
,
__func__
,
stat
);
pr
_debug
(
"%s: Error detected in status(0x%X)!
\n
"
,
__func__
,
stat
);
return
-
EIO
;
}
if
(
!
transfer_done
&&
(
stat
&
rdy
))
{
...
...
@@ -594,7 +594,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
if
(
host
->
quirks
&
SDHCI_QUIRK_BROKEN_VOLTAGE
)
cfg
->
voltages
|=
host
->
voltages
;
cfg
->
host_caps
=
MMC_MODE_HS
|
MMC_MODE_HS_52MHz
|
MMC_MODE_4BIT
;
cfg
->
host_caps
|
=
MMC_MODE_HS
|
MMC_MODE_HS_52MHz
|
MMC_MODE_4BIT
;
/* Since Host Controller Version3.0 */
if
(
SDHCI_GET_VERSION
(
host
)
>=
SDHCI_SPEC_300
)
{
...
...
drivers/power/pmic/s2mps11.c
浏览文件 @
fb441329
...
...
@@ -15,6 +15,12 @@
DECLARE_GLOBAL_DATA_PTR
;
static
const
struct
pmic_child_info
pmic_children_info
[]
=
{
{
.
prefix
=
S2MPS11_OF_LDO_PREFIX
,
.
driver
=
S2MPS11_LDO_DRIVER
},
{
.
prefix
=
S2MPS11_OF_BUCK_PREFIX
,
.
driver
=
S2MPS11_BUCK_DRIVER
},
{
},
};
static
int
s2mps11_reg_count
(
struct
udevice
*
dev
)
{
return
S2MPS11_REG_COUNT
;
...
...
@@ -43,6 +49,27 @@ static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
return
ret
;
}
static
int
s2mps11_probe
(
struct
udevice
*
dev
)
{
ofnode
regulators_node
;
int
children
;
regulators_node
=
dev_read_subnode
(
dev
,
"voltage-regulators"
);
if
(
!
ofnode_valid
(
regulators_node
))
{
debug
(
"%s: %s regulators subnode not found!"
,
__func__
,
dev
->
name
);
return
-
ENXIO
;
}
debug
(
"%s: '%s' - found regulators subnode
\n
"
,
__func__
,
dev
->
name
);
children
=
pmic_bind_children
(
dev
,
regulators_node
,
pmic_children_info
);
if
(
!
children
)
debug
(
"%s: %s - no child found
\n
"
,
__func__
,
dev
->
name
);
return
0
;
}
static
struct
dm_pmic_ops
s2mps11_ops
=
{
.
reg_count
=
s2mps11_reg_count
,
.
read
=
s2mps11_read
,
...
...
@@ -59,4 +86,5 @@ U_BOOT_DRIVER(pmic_s2mps11) = {
.
id
=
UCLASS_PMIC
,
.
of_match
=
s2mps11_ids
,
.
ops
=
&
s2mps11_ops
,
.
probe
=
s2mps11_probe
,
};
drivers/power/regulator/Kconfig
浏览文件 @
fb441329
...
...
@@ -101,6 +101,14 @@ config REGULATOR_RK8XX
by the PMIC device. This driver is controlled by a device tree node
which includes voltage limits.
config DM_REGULATOR_S2MPS11
bool "Enable driver for S2MPS11 regulator"
depends on DM_REGULATOR && PMIC_S2MPS11
---help---
This enables implementation of driver-model regulator uclass
features for REGULATOR S2MPS11.
The driver implements get/set api for: value and enable.
config REGULATOR_S5M8767
bool "Enable support for S5M8767 regulator"
depends on DM_REGULATOR && PMIC_S5M8767
...
...
drivers/power/regulator/Makefile
浏览文件 @
fb441329
...
...
@@ -14,6 +14,7 @@ obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED)
+=
fixed.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO)
+=
gpio-regulator.o
obj-$(CONFIG_REGULATOR_RK8XX)
+=
rk8xx.o
obj-$(CONFIG_DM_REGULATOR_S2MPS11)
+=
s2mps11_regulator.o
obj-$(CONFIG_REGULATOR_S5M8767)
+=
s5m8767.o
obj-$(CONFIG_DM_REGULATOR_SANDBOX)
+=
sandbox.o
obj-$(CONFIG_REGULATOR_TPS65090)
+=
tps65090_regulator.o
...
...
drivers/power/regulator/s2mps11_regulator.c
0 → 100644
浏览文件 @
fb441329
/*
* Copyright (C) 2018 Samsung Electronics
* Jaehoon Chung <jh80.chung@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <i2c.h>
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/s2mps11.h>
DECLARE_GLOBAL_DATA_PTR
;
#define MODE(_id, _val, _name) { \
.id = _id, \
.register_value = _val, \
.name = _name, \
}
/* BUCK : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 */
static
struct
dm_regulator_mode
s2mps11_buck_modes
[]
=
{
MODE
(
OP_OFF
,
S2MPS11_BUCK_MODE_OFF
,
"OFF"
),
MODE
(
OP_STANDBY
,
S2MPS11_BUCK_MODE_STANDBY
,
"ON/OFF"
),
MODE
(
OP_ON
,
S2MPS11_BUCK_MODE_STANDBY
,
"ON"
),
};
static
struct
dm_regulator_mode
s2mps11_ldo_modes
[]
=
{
MODE
(
OP_OFF
,
S2MPS11_LDO_MODE_OFF
,
"OFF"
),
MODE
(
OP_STANDBY
,
S2MPS11_LDO_MODE_STANDBY
,
"ON/OFF"
),
MODE
(
OP_STANDBY_LPM
,
S2MPS11_LDO_MODE_STANDBY_LPM
,
"ON/LPM"
),
MODE
(
OP_ON
,
S2MPS11_LDO_MODE_ON
,
"ON"
),
};
static
const
char
s2mps11_buck_ctrl
[]
=
{
0xff
,
0x25
,
0x27
,
0x29
,
0x2b
,
0x2d
,
0x33
,
0x35
,
0x37
,
0x39
,
0x3b
};
static
const
char
s2mps11_buck_out
[]
=
{
0xff
,
0x26
,
0x28
,
0x2a
,
0x2c
,
0x2f
,
0x34
,
0x36
,
0x38
,
0x3a
,
0x3c
};
static
int
s2mps11_buck_hex2volt
(
int
buck
,
int
hex
)
{
unsigned
int
uV
=
0
;
if
(
hex
<
0
)
goto
bad
;
switch
(
buck
)
{
case
7
:
case
8
:
case
10
:
if
(
hex
>
S2MPS11_BUCK7_8_10_VOLT_MAX_HEX
)
goto
bad
;
uV
=
hex
*
S2MPS11_BUCK_HSTEP
+
S2MPS11_BUCK_UV_HMIN
;
break
;
case
9
:
if
(
hex
>
S2MPS11_BUCK9_VOLT_MAX_HEX
)
goto
bad
;
uV
=
hex
*
S2MPS11_BUCK9_STEP
*
2
+
S2MPS11_BUCK9_UV_MIN
;
break
;
default:
if
(
buck
==
5
&&
hex
>
S2MPS11_BUCK5_VOLT_MAX_HEX
)
goto
bad
;
else
if
(
buck
!=
5
&&
hex
>
S2MPS11_BUCK_VOLT_MAX_HEX
)
goto
bad
;
uV
=
hex
*
S2MPS11_BUCK_LSTEP
+
S2MPS11_BUCK_UV_MIN
;
break
;
}
return
uV
;
bad:
pr_err
(
"Value: %#x is wrong for BUCK%d"
,
hex
,
buck
);
return
-
EINVAL
;
}
static
int
s2mps11_buck_volt2hex
(
int
buck
,
int
uV
)
{
int
hex
;
switch
(
buck
)
{
case
7
:
case
8
:
case
10
:
hex
=
(
uV
-
S2MPS11_BUCK_UV_HMIN
)
/
S2MPS11_BUCK_HSTEP
;
if
(
hex
>
S2MPS11_BUCK7_8_10_VOLT_MAX_HEX
)
goto
bad
;
break
;
case
9
:
hex
=
(
uV
-
S2MPS11_BUCK9_UV_MIN
)
/
S2MPS11_BUCK9_STEP
;
if
(
hex
>
S2MPS11_BUCK9_VOLT_MAX_HEX
)
goto
bad
;
break
;
default:
hex
=
(
uV
-
S2MPS11_BUCK_UV_MIN
)
/
S2MPS11_BUCK_LSTEP
;
if
(
buck
==
5
&&
hex
>
S2MPS11_BUCK5_VOLT_MAX_HEX
)
goto
bad
;
else
if
(
buck
!=
5
&&
hex
>
S2MPS11_BUCK_VOLT_MAX_HEX
)
goto
bad
;
break
;
};
if
(
hex
>=
0
)
return
hex
;
bad:
pr_err
(
"Value: %d uV is wrong for BUCK%d"
,
uV
,
buck
);
return
-
EINVAL
;
}
static
int
s2mps11_buck_val
(
struct
udevice
*
dev
,
int
op
,
int
*
uV
)
{
int
hex
,
buck
,
ret
;
u32
mask
,
addr
;
u8
val
;
buck
=
dev
->
driver_data
;
if
(
buck
<
1
||
buck
>
S2MPS11_BUCK_NUM
)
{
pr_err
(
"Wrong buck number: %d
\n
"
,
buck
);
return
-
EINVAL
;
}
if
(
op
==
PMIC_OP_GET
)
*
uV
=
0
;
addr
=
s2mps11_buck_out
[
buck
];
switch
(
buck
)
{
case
9
:
mask
=
S2MPS11_BUCK9_VOLT_MASK
;
break
;
default:
mask
=
S2MPS11_BUCK_VOLT_MASK
;
break
;
}
ret
=
pmic_read
(
dev
->
parent
,
addr
,
&
val
,
1
);
if
(
ret
)
return
ret
;
if
(
op
==
PMIC_OP_GET
)
{
val
&=
mask
;
ret
=
s2mps11_buck_hex2volt
(
buck
,
val
);
if
(
ret
<
0
)
return
ret
;
*
uV
=
ret
;
return
0
;
}
hex
=
s2mps11_buck_volt2hex
(
buck
,
*
uV
);
if
(
hex
<
0
)
return
hex
;
val
&=
~
mask
;
val
|=
hex
;
ret
=
pmic_write
(
dev
->
parent
,
addr
,
&
val
,
1
);
return
ret
;
}
static
int
s2mps11_buck_mode
(
struct
udevice
*
dev
,
int
op
,
int
*
opmode
)
{
unsigned
int
addr
,
mode
;
unsigned
char
val
;
int
buck
,
ret
;
buck
=
dev
->
driver_data
;
if
(
buck
<
1
||
buck
>
S2MPS11_BUCK_NUM
)
{
pr_err
(
"Wrong buck number: %d
\n
"
,
buck
);
return
-
EINVAL
;
}
addr
=
s2mps11_buck_ctrl
[
buck
];
ret
=
pmic_read
(
dev
->
parent
,
addr
,
&
val
,
1
);
if
(
ret
)
return
ret
;
if
(
op
==
PMIC_OP_GET
)
{
val
&=
(
S2MPS11_BUCK_MODE_MASK
<<
S2MPS11_BUCK_MODE_SHIFT
);
switch
(
val
)
{
case
S2MPS11_BUCK_MODE_OFF
:
*
opmode
=
OP_OFF
;
break
;
case
S2MPS11_BUCK_MODE_STANDBY
:
*
opmode
=
OP_STANDBY
;
break
;
case
S2MPS11_BUCK_MODE_ON
:
*
opmode
=
OP_ON
;
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
switch
(
*
opmode
)
{
case
OP_OFF
:
mode
=
S2MPS11_BUCK_MODE_OFF
;
break
;
case
OP_STANDBY
:
mode
=
S2MPS11_BUCK_MODE_STANDBY
;
break
;
case
OP_ON
:
mode
=
S2MPS11_BUCK_MODE_ON
;
break
;
default:
pr_err
(
"Wrong mode: %d for buck: %d
\n
"
,
*
opmode
,
buck
);
return
-
EINVAL
;
}
val
&=
~
(
S2MPS11_BUCK_MODE_MASK
<<
S2MPS11_BUCK_MODE_SHIFT
);
val
|=
mode
;
ret
=
pmic_write
(
dev
->
parent
,
addr
,
&
val
,
1
);
return
ret
;
}
static
int
s2mps11_buck_enable
(
struct
udevice
*
dev
,
int
op
,
bool
*
enable
)
{
int
ret
,
on_off
;
if
(
op
==
PMIC_OP_GET
)
{
ret
=
s2mps11_buck_mode
(
dev
,
op
,
&
on_off
);
if
(
ret
)
return
ret
;
switch
(
on_off
)
{
case
OP_OFF
:
*
enable
=
false
;
break
;
case
OP_ON
:
*
enable
=
true
;
break
;
default:
return
-
EINVAL
;
}
}
else
if
(
op
==
PMIC_OP_SET
)
{
if
(
*
enable
)
on_off
=
OP_ON
;
else
on_off
=
OP_OFF
;
ret
=
s2mps11_buck_mode
(
dev
,
op
,
&
on_off
);
if
(
ret
)
return
ret
;
}
return
0
;
}
static
int
buck_get_value
(
struct
udevice
*
dev
)
{
int
uV
;
int
ret
;
ret
=
s2mps11_buck_val
(
dev
,
PMIC_OP_GET
,
&
uV
);
if
(
ret
)
return
ret
;
return
uV
;
}
static
int
buck_set_value
(
struct
udevice
*
dev
,
int
uV
)
{
return
s2mps11_buck_val
(
dev
,
PMIC_OP_SET
,
&
uV
);
}
static
int
buck_get_enable
(
struct
udevice
*
dev
)
{
bool
enable
=
false
;
int
ret
;
ret
=
s2mps11_buck_enable
(
dev
,
PMIC_OP_GET
,
&
enable
);
if
(
ret
)
return
ret
;
return
enable
;
}
static
int
buck_set_enable
(
struct
udevice
*
dev
,
bool
enable
)
{
return
s2mps11_buck_enable
(
dev
,
PMIC_OP_SET
,
&
enable
);
}
static
int
buck_get_mode
(
struct
udevice
*
dev
)
{
int
mode
;
int
ret
;
ret
=
s2mps11_buck_mode
(
dev
,
PMIC_OP_GET
,
&
mode
);
if
(
ret
)
return
ret
;
return
mode
;
}
static
int
buck_set_mode
(
struct
udevice
*
dev
,
int
mode
)
{
return
s2mps11_buck_mode
(
dev
,
PMIC_OP_SET
,
&
mode
);
}
static
int
s2mps11_buck_probe
(
struct
udevice
*
dev
)
{
struct
dm_regulator_uclass_platdata
*
uc_pdata
;
uc_pdata
=
dev_get_uclass_platdata
(
dev
);
uc_pdata
->
type
=
REGULATOR_TYPE_BUCK
;
uc_pdata
->
mode
=
s2mps11_buck_modes
;
uc_pdata
->
mode_count
=
ARRAY_SIZE
(
s2mps11_buck_modes
);
return
0
;
}
static
const
struct
dm_regulator_ops
s2mps11_buck_ops
=
{
.
get_value
=
buck_get_value
,
.
set_value
=
buck_set_value
,
.
get_enable
=
buck_get_enable
,
.
set_enable
=
buck_set_enable
,
.
get_mode
=
buck_get_mode
,
.
set_mode
=
buck_set_mode
,
};
U_BOOT_DRIVER
(
s2mps11_buck
)
=
{
.
name
=
S2MPS11_BUCK_DRIVER
,
.
id
=
UCLASS_REGULATOR
,
.
ops
=
&
s2mps11_buck_ops
,
.
probe
=
s2mps11_buck_probe
,
};
static
int
s2mps11_ldo_hex2volt
(
int
ldo
,
int
hex
)
{
unsigned
int
uV
=
0
;
if
(
hex
>
S2MPS11_LDO_VOLT_MAX_HEX
)
{
pr_err
(
"Value: %#x is wrong for LDO%d"
,
hex
,
ldo
);
return
-
EINVAL
;
}
switch
(
ldo
)
{
case
1
:
case
6
:
case
11
:
case
22
:
case
23
:
uV
=
hex
*
S2MPS11_LDO_STEP
+
S2MPS11_LDO_UV_MIN
;
break
;
default:
uV
=
hex
*
S2MPS11_LDO_STEP
*
2
+
S2MPS11_LDO_UV_MIN
;
break
;
}
return
uV
;
}
static
int
s2mps11_ldo_volt2hex
(
int
ldo
,
int
uV
)
{
int
hex
=
0
;
switch
(
ldo
)
{
case
1
:
case
6
:
case
11
:
case
22
:
case
23
:
hex
=
(
uV
-
S2MPS11_LDO_UV_MIN
)
/
S2MPS11_LDO_STEP
;
break
;
default:
hex
=
(
uV
-
S2MPS11_LDO_UV_MIN
)
/
(
S2MPS11_LDO_STEP
*
2
);
break
;
}
if
(
hex
>=
0
&&
hex
<=
S2MPS11_LDO_VOLT_MAX_HEX
)
return
hex
;
pr_err
(
"Value: %d uV is wrong for LDO%d"
,
uV
,
ldo
);
return
-
EINVAL
;
return
0
;
}
static
int
s2mps11_ldo_val
(
struct
udevice
*
dev
,
int
op
,
int
*
uV
)
{
unsigned
int
addr
;
unsigned
char
val
;
int
hex
,
ldo
,
ret
;
ldo
=
dev
->
driver_data
;
if
(
ldo
<
1
||
ldo
>
S2MPS11_LDO_NUM
)
{
pr_err
(
"Wrong ldo number: %d
\n
"
,
ldo
);
return
-
EINVAL
;
}
addr
=
S2MPS11_REG_L1CTRL
+
ldo
-
1
;
ret
=
pmic_read
(
dev
->
parent
,
addr
,
&
val
,
1
);
if
(
ret
)
return
ret
;
if
(
op
==
PMIC_OP_GET
)
{
*
uV
=
0
;
val
&=
S2MPS11_LDO_VOLT_MASK
;
ret
=
s2mps11_ldo_hex2volt
(
ldo
,
val
);
if
(
ret
<
0
)
return
ret
;
*
uV
=
ret
;
return
0
;
}
hex
=
s2mps11_ldo_volt2hex
(
ldo
,
*
uV
);
if
(
hex
<
0
)
return
hex
;
val
&=
~
S2MPS11_LDO_VOLT_MASK
;
val
|=
hex
;
ret
=
pmic_write
(
dev
->
parent
,
addr
,
&
val
,
1
);
return
ret
;
}
static
int
s2mps11_ldo_mode
(
struct
udevice
*
dev
,
int
op
,
int
*
opmode
)
{
unsigned
int
addr
,
mode
;
unsigned
char
val
;
int
ldo
,
ret
;
ldo
=
dev
->
driver_data
;
if
(
ldo
<
1
||
ldo
>
S2MPS11_LDO_NUM
)
{
pr_err
(
"Wrong ldo number: %d
\n
"
,
ldo
);
return
-
EINVAL
;
}
addr
=
S2MPS11_REG_L1CTRL
+
ldo
-
1
;
ret
=
pmic_read
(
dev
->
parent
,
addr
,
&
val
,
1
);
if
(
ret
)
return
ret
;
if
(
op
==
PMIC_OP_GET
)
{
val
&=
(
S2MPS11_LDO_MODE_MASK
<<
S2MPS11_LDO_MODE_SHIFT
);
switch
(
val
)
{
case
S2MPS11_LDO_MODE_OFF
:
*
opmode
=
OP_OFF
;
break
;
case
S2MPS11_LDO_MODE_STANDBY
:
*
opmode
=
OP_STANDBY
;
break
;
case
S2MPS11_LDO_MODE_STANDBY_LPM
:
*
opmode
=
OP_STANDBY_LPM
;
break
;
case
S2MPS11_LDO_MODE_ON
:
*
opmode
=
OP_ON
;
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
switch
(
*
opmode
)
{
case
OP_OFF
:
mode
=
S2MPS11_LDO_MODE_OFF
;
break
;
case
OP_STANDBY
:
mode
=
S2MPS11_LDO_MODE_STANDBY
;
break
;
case
OP_STANDBY_LPM
:
mode
=
S2MPS11_LDO_MODE_STANDBY_LPM
;
break
;
case
OP_ON
:
mode
=
S2MPS11_LDO_MODE_ON
;
break
;
default:
pr_err
(
"Wrong mode: %d for ldo: %d
\n
"
,
*
opmode
,
ldo
);
return
-
EINVAL
;
}
val
&=
~
(
S2MPS11_LDO_MODE_MASK
<<
S2MPS11_LDO_MODE_SHIFT
);
val
|=
mode
;
ret
=
pmic_write
(
dev
->
parent
,
addr
,
&
val
,
1
);
return
ret
;
}
static
int
s2mps11_ldo_enable
(
struct
udevice
*
dev
,
int
op
,
bool
*
enable
)
{
int
ret
,
on_off
;
if
(
op
==
PMIC_OP_GET
)
{
ret
=
s2mps11_ldo_mode
(
dev
,
op
,
&
on_off
);
if
(
ret
)
return
ret
;
switch
(
on_off
)
{
case
OP_OFF
:
*
enable
=
false
;
break
;
case
OP_ON
:
*
enable
=
true
;
break
;
default:
return
-
EINVAL
;
}
}
else
if
(
op
==
PMIC_OP_SET
)
{
if
(
*
enable
)
on_off
=
OP_ON
;
else
on_off
=
OP_OFF
;
ret
=
s2mps11_ldo_mode
(
dev
,
op
,
&
on_off
);
if
(
ret
)
return
ret
;
}
return
0
;
}
static
int
ldo_get_value
(
struct
udevice
*
dev
)
{
int
uV
;
int
ret
;
ret
=
s2mps11_ldo_val
(
dev
,
PMIC_OP_GET
,
&
uV
);
if
(
ret
)
return
ret
;
return
uV
;
}
static
int
ldo_set_value
(
struct
udevice
*
dev
,
int
uV
)
{
return
s2mps11_ldo_val
(
dev
,
PMIC_OP_SET
,
&
uV
);
}
static
int
ldo_get_enable
(
struct
udevice
*
dev
)
{
bool
enable
=
false
;
int
ret
;
ret
=
s2mps11_ldo_enable
(
dev
,
PMIC_OP_GET
,
&
enable
);
if
(
ret
)
return
ret
;
return
enable
;
}
static
int
ldo_set_enable
(
struct
udevice
*
dev
,
bool
enable
)
{
return
s2mps11_ldo_enable
(
dev
,
PMIC_OP_SET
,
&
enable
);
}
static
int
ldo_get_mode
(
struct
udevice
*
dev
)
{
int
mode
,
ret
;
ret
=
s2mps11_ldo_mode
(
dev
,
PMIC_OP_GET
,
&
mode
);
if
(
ret
)
return
ret
;
return
mode
;
}
static
int
ldo_set_mode
(
struct
udevice
*
dev
,
int
mode
)
{
return
s2mps11_ldo_mode
(
dev
,
PMIC_OP_SET
,
&
mode
);
}
static
int
s2mps11_ldo_probe
(
struct
udevice
*
dev
)
{
struct
dm_regulator_uclass_platdata
*
uc_pdata
;
uc_pdata
=
dev_get_uclass_platdata
(
dev
);
uc_pdata
->
type
=
REGULATOR_TYPE_LDO
;
uc_pdata
->
mode
=
s2mps11_ldo_modes
;
uc_pdata
->
mode_count
=
ARRAY_SIZE
(
s2mps11_ldo_modes
);
return
0
;
}
static
const
struct
dm_regulator_ops
s2mps11_ldo_ops
=
{
.
get_value
=
ldo_get_value
,
.
set_value
=
ldo_set_value
,
.
get_enable
=
ldo_get_enable
,
.
set_enable
=
ldo_set_enable
,
.
get_mode
=
ldo_get_mode
,
.
set_mode
=
ldo_set_mode
,
};
U_BOOT_DRIVER
(
s2mps11_ldo
)
=
{
.
name
=
S2MPS11_LDO_DRIVER
,
.
id
=
UCLASS_REGULATOR
,
.
ops
=
&
s2mps11_ldo_ops
,
.
probe
=
s2mps11_ldo_probe
,
};
include/dm/read.h
浏览文件 @
fb441329
...
...
@@ -45,6 +45,16 @@ static inline bool dev_of_valid(struct udevice *dev)
}
#ifndef CONFIG_DM_DEV_READ_INLINE
/**
* dev_read_u32() - read a 32-bit integer from a device's DT property
*
* @dev: device to read DT property from
* @propname: name of the property to read from
* @outp: place to put value (if found)
* @return 0 if OK, -ve on error
*/
int
dev_read_u32
(
struct
udevice
*
dev
,
const
char
*
propname
,
u32
*
outp
);
/**
* dev_read_u32_default() - read a 32-bit integer from a device's DT property
*
...
...
@@ -424,6 +434,12 @@ int dev_read_resource_byname(struct udevice *dev, const char *name,
u64
dev_translate_address
(
struct
udevice
*
dev
,
const
fdt32_t
*
in_addr
);
#else
/* CONFIG_DM_DEV_READ_INLINE is enabled */
static
inline
int
dev_read_u32
(
struct
udevice
*
dev
,
const
char
*
propname
,
u32
*
outp
)
{
return
ofnode_read_u32
(
dev_ofnode
(
dev
),
propname
,
outp
);
}
static
inline
int
dev_read_u32_default
(
struct
udevice
*
dev
,
const
char
*
propname
,
int
def
)
{
...
...
include/power/s2mps11.h
浏览文件 @
fb441329
...
...
@@ -106,4 +106,59 @@ enum s2mps11_reg {
#define S2MPS11_LDO26_ENABLE 0xec
#define S2MPS11_LDO_NUM 26
#define S2MPS11_BUCK_NUM 10
/* Driver name */
#define S2MPS11_BUCK_DRIVER "s2mps11_buck"
#define S2MPS11_OF_BUCK_PREFIX "BUCK"
#define S2MPS11_LDO_DRIVER "s2mps11_ldo"
#define S2MPS11_OF_LDO_PREFIX "LDO"
/* BUCK */
#define S2MPS11_BUCK_VOLT_MASK 0xff
#define S2MPS11_BUCK9_VOLT_MASK 0x1f
#define S2MPS11_BUCK_LSTEP 6250
#define S2MPS11_BUCK_HSTEP 12500
#define S2MPS11_BUCK9_STEP 25000
#define S2MPS11_BUCK_UV_MIN 600000
#define S2MPS11_BUCK_UV_HMIN 750000
#define S2MPS11_BUCK9_UV_MIN 1400000
#define S2MPS11_BUCK_VOLT_MAX_HEX 0xA0
#define S2MPS11_BUCK5_VOLT_MAX_HEX 0xDF
#define S2MPS11_BUCK7_8_10_VOLT_MAX_HEX 0xDC
#define S2MPS11_BUCK9_VOLT_MAX_HEX 0x5F
#define S2MPS11_BUCK_MODE_SHIFT 6
#define S2MPS11_BUCK_MODE_MASK (0x3)
#define S2MPS11_BUCK_MODE_OFF (0x0 << 6)
#define S2MPS11_BUCK_MODE_STANDBY (0x1 << 6)
#define S2MPS11_BUCK_MODE_ON (0x3 << 6)
/* LDO */
#define S2MPS11_LDO_VOLT_MASK 0x3F
#define S2MPS11_LDO_VOLT_MAX_HEX 0x3F
#define S2MPS11_LDO_STEP 25000
#define S2MPS11_LDO_UV_MIN 800000
#define S2MPS11_LDO_MODE_MASK 0x3
#define S2MPS11_LDO_MODE_SHIFT 6
#define S2MPS11_LDO_MODE_OFF (0x0 << 6)
#define S2MPS11_LDO_MODE_STANDBY (0x1 << 6)
#define S2MPS11_LDO_MODE_STANDBY_LPM (0x2 << 6)
#define S2MPS11_LDO_MODE_ON (0x3 << 6)
enum
{
OP_OFF
=
0
,
OP_LPM
,
OP_STANDBY
,
OP_STANDBY_LPM
,
OP_ON
,
};
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录