EDA365电子论坛网

标题: 学习嵌入式小白基于4412修改电源管理芯片8767电压输出 [打印本页]

作者: 孟亚凡    时间: 2019-12-31 15:18
标题: 学习嵌入式小白基于4412修改电源管理芯片8767电压输出
这周技术支持的时候遇到一个小伙伴,想把底板上2.8v的输出修改为3.3v,但是不知道要从哪入手,所以,法师推文的素材就又有了~~~这位小伙伴看到记得给点个赞呐~- d2 g  p/ e3 \0 S( O
S5M8767电源管理芯片是三星专门针对4412研发的,S5M8767提供9路BUCK和28路LDO输出,每路电压的大小可以通过软件进行设置。这里我们以迅为-4412精英底板VDD28_AF,VDD28_CAM这俩路为例。
3 R" }( E* b7 s; O: [9 Q原理图分析
. X* ^2 h/ ^' u! q  b在底板原理图中找到camera扩展端子,camera摄像头驱动中将这俩路电压设置为2.8v 的电压。所以在后面我们修改这俩路电压的时候要先去掉摄像的驱动。
通过核心板原理图可知,VDD28_AF和VDD28_CAM分别对应电源芯片 S5M8767A 的VLDO20和VLDO21。如下图所示:
然后我们打开8767的datasheet,找到对这俩路的描述,下图最上面的红框中,表示输出的电流是150mA,最低输出电压是0.8v,最大电压是3.95v。最下面的红框中,介绍的是默认输出电压,可以看到LDO20和LDO21,默认输出的是3.0v。如下图所示:
软件分析
     确定完硬件原理之后,我们知道这俩路的电压范围是0.8v到3.95v。然后我们打开内核源码里面的平台文件。
平台文件位置:
rch/arm/mach-exynos/mach-itop4412.c
% U0 e0 M) u6 ?8 j然后我们找到对应ldo20和ldo21的代码,如下图所示:
我们将红框的中的代码2800000修改为3950000,红框函数中的第一个参数表示8767电源芯片的第20路,第三个参数表示输出最低电压,第四个参数表示输出最高电压。
     最后我们还要在menuconfig里面将5640的驱动去掉。这样我们软件的配置就完成了。
测试
     测试代码如下:
#include <linux/init.h>4 }/ s2 M3 L0 d9 w8 p# k5 U7 l! e
#include <linux/module.h>
% {( _0 o5 ^% y/ r+ D4 B) ]- m#include <linux/i2c.h>* t6 G" j0 p' p" e
#include <linux/platform_device.h>
; U, I. Q" f8 P' r* q0 z- R0 t5 R#include <linux/delay.h># S4 ^4 d3 r& R1 w; W
#include <linux/regulator/consumer.h>
  S6 W" q" @8 N! `2 l1 [#include <mach/gpio.h>8 G% a0 E: z$ z3 {) a# }2 l& X$ W4 Z" K
#include <plat/gpio-cfg.h>
$ |5 H9 e" L6 G( |#include <mach/regs-gpio.h>
8 k" S7 n. I9 {3 D& J# u% n' S, o8 D#include <mach/regs-clock.h>
% z  `5 m! z3 y( H#include <linux/fs.h>
" [$ p8 f/ Y2 f+ @9 [) O* C: k# M#include <linux/err.h>9 v7 a4 u& e5 ^# M7 {% @* n) C
struct regulator *ov_vddaf_cam_regulator = NULL;
. N9 [0 T" g9 ]' g% k  Hstruct regulator *ov_vdd5m_cam_regulator = NULL;
. M; u% p5 s+ V3 N+ P5 O8 `* Lstruct regulator *ov_vdd18_cam_regulator = NULL;
6 |6 |3 m9 M6 w- |# Ystruct regulator *ov_vdd28_cam_regulator = NULL;
/ a# g0 C: F0 R4 ?) iMODULE_LICENSE("Dual BSD/GPL");
4 t" ~: R# V1 d( {0 nMODULE_AUTHOR("iTOPEET_dz");: z4 p5 w5 D# }; Y* h  h' Z2 [$ N* n+ U
static int power(int flag)
1 \* r6 o1 x; F" k- _{1 e. t0 \9 C5 D' M
if(1 == flag){regulator_enable(ov_vdd18_cam_regulator);
9 p; R; M) W9 \3 P  F6 ]) \udelay(10);: @9 L5 w- r. Z6 v) L1 W$ [
regulator_enable(ov_vdd28_cam_regulator);
' f* I' c/ V" S$ |! F0 c' q9 oudelay(10);. b, r* z% S" W4 v: h
regulator_enable(ov_vdd5m_cam_regulator); //DOVDD DVDD 1.8v
  j1 _& ]' O, V# I  f4 x' L% o0 H, Xudelay(10);
& [6 o2 M/ @# v9 L+ Tregulator_enable(ov_vddaf_cam_regulator); //AVDD 2.8v
: E" U( K) x. U2 v! S* L. tudelay(10);
& d* [& m. w# b}( G( h6 _% F6 T5 h8 b. X( T, ^4 X
else if(0 == flag){
# k- i1 X4 L1 Y, _regulator_disable(ov_vdd18_cam_regulator);- p1 L5 R! N2 x  x9 R, N8 |1 z  H
udelay(10);# ~; Q5 ~, {' L. `
regulator_disable(ov_vdd28_cam_regulator);
. K) b) C0 a6 d! w; P4 X5 judelay(10);regulator_disable(ov_vdd5m_cam_regulator);, w  O5 s* ^: \; K% {, i
udelay(10);regulator_disable(ov_vddaf_cam_regulator);
! m% n* g4 u$ W2 a9 ~udelay(10);
+ S" P6 V5 j" `6 v}/ N7 p  B" ?! \. `% G2 L$ V
return 0 ;5 R) b$ {) E9 A
}
/ ?5 o0 ~. V% o& i5 z0 j+ Tstatic void power_init(void); x4 P, k& Y: _  n
{3 `5 O4 W& b9 C- A
int ret;1 M0 ]/ @: z0 G, d. p
ov_vdd18_cam_regulator = regulator_get(NULL, "vdd18_cam");
6 c" z; p8 [4 i5 L1 j1 T5 |$ vif (IS_ERR(ov_vdd18_cam_regulator)) {5 o+ Y$ T/ v+ p4 M0 ~$ f7 H3 ^
printk("%s: failed to get %s\n", __func__, "vdd18_cam");  ^+ C) u5 m- K. G7 M
ret = -ENODEV;; F. K9 I1 U% f; p$ s
goto err_regulator;}ov_vdd28_cam_regulator = regulator_get(NULL, "vdda28_2m");
6 J/ ]: c6 s% ]3 Yif (IS_ERR(ov_vdd28_cam_regulator)) {4 V- s  L# e5 G: Y
printk("%s: failed to get %s\n", __func__, "vdda28_2m");" Z: S/ F! V9 x! X: K$ b
ret = -ENODEV;
2 g5 S) [7 r# ~  ]0 |1 ^goto err_regulator;
$ J5 n( k! h+ Z8 I# y- k* R  s}2 i& z% _' g0 C% L0 l
ov_vddaf_cam_regulator = regulator_get(NULL, "vdd28_af");0 Q; t/ c, x. O" J
if (IS_ERR(ov_vddaf_cam_regulator)) {. W; b- C, E' C/ j
printk("%s: failed to get %s\n", __func__, "vdd28_af");* g! H1 D: C4 w
ret = -ENODEV;goto err_regulator;
% ?- L7 u( V" C/ S( t8 e+ X0 D}% P3 F# `- x2 v5 J# s* t2 T
ov_vdd5m_cam_regulator = regulator_get(NULL, "vdd28_cam");" F- O* @# P3 t7 `; F
if (IS_ERR(ov_vdd5m_cam_regulator)) {
1 G: u9 X" b9 L  z' m3 f! Rprintk("%s: failed to get %s\n", __func__, "vdd28_cam");) U# H: U' _1 T: G. K& n
ret = -ENODEV;goto err_regulator;1 Z3 N% U( \) E5 ~
}! h7 h# a: }* l- N* ^; x  S
err_regulator:
: ?1 `( l4 K( J$ lregulator_put(ov_vddaf_cam_regulator);
2 ~$ R9 g+ |% D( y% ]regulator_put(ov_vdd5m_cam_regulator);6 H% i7 U8 o% R! k9 q2 A: P
regulator_put(ov_vdd18_cam_regulator);# k3 E. V: W; z! K- E
regulator_put(ov_vdd28_cam_regulator);" r$ L$ a: ~' g$ A1 A1 I
}
; S4 S: x* G8 R) Mstatic int hello_init(void)' W- w7 Z# e8 E3 R! r( W
{
! q. i$ G. {8 v: n% J) ipower_init();. m, M2 A( [" [7 g3 R; O# V# V
power(1);
, x5 w) X' U+ k1 [& Tprintk(KERN_EMERG "Hello World enter!\n");+ p) X$ j0 c% D& T+ u
return 0;
: A# l( v( A- q( o}
1 \7 n( T0 B! p8 Q6 r9 P6 A* E8 Astatic void hello_exit(void)9 J. }+ i7 G* K
{
/ m% H7 k: P( M# spower(0);. ~9 u2 y+ m& x7 G6 c8 R! i
printk(KERN_EMERG "Hello world exit!\n");
, I& U: y: g# w9 _1 b}% a( F8 m8 n' X- ~: b3 o. K
module_init(hello_init);1 F+ R4 z8 b4 b# L/ L
module_exit(hello_exit);
& b) q4 }. F8 t0 s1 P+ P3 g6 \; K9 S) n3 q0 A! ~
Makefile如下所示。
% |0 _4 x/ W8 B. q0 l8 w#!/bin/bash
5 m  s' N3 W" `. p7 V1 h2 Pobj-m += power_s5m8767a_test.o5 b. J4 n1 X( j2 P9 ?- G: H8 I( m
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0
, V1 [$ l& X/ q  GPWD ?= $(shell pwd)
& n: e1 |8 J2 M) p* v7 m( H  U# Dall:# s- f$ F. Q8 r/ C2 n
make -C $(KDIR) M=$(PWD) modules' R) f% M8 }% S5 g
clean:
/ F. T" R) k5 a1 i3 [2 Vrm -rf *.o modules.order *.ko *mod.c Module.symvers
. X. r- P; F/ e4 F  t我们加载驱动之后,测量电压大约为3V左右,有压降,卸载驱动之后,电压为0。说明驱动运行成功,如果在自己的项目中,假如需要用到电源控制,也可以参考本例程来实现。

, Z+ d) N0 @% S( h( C




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2