Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
867fe7c3
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
867fe7c3
编写于
2月 25, 2015
作者:
S
Sebastian Reichel
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'da9150-charger-fuelgauge' into next
上级
4bf828cf
adcf30bf
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
433 addition
and
0 deletion
+433
-0
Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
+16
-0
drivers/iio/adc/Kconfig
drivers/iio/adc/Kconfig
+9
-0
drivers/iio/adc/Makefile
drivers/iio/adc/Makefile
+1
-0
drivers/iio/adc/da9150-gpadc.c
drivers/iio/adc/da9150-gpadc.c
+407
-0
未找到文件。
Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
0 → 100644
浏览文件 @
867fe7c3
Dialog Semiconductor DA9150 IIO GPADC bindings
Required properties:
- compatible: "dlg,da9150-gpadc" for DA9150 IIO GPADC
- #io-channel-cells: Should be set to <1>
(See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
For further information on GPADC channels, see device datasheet.
Example:
gpadc: da9150-gpadc {
compatible = "dlg,da9150-gpadc";
#io-channel-cells = <1>;
};
drivers/iio/adc/Kconfig
浏览文件 @
867fe7c3
...
@@ -135,6 +135,15 @@ config AXP288_ADC
...
@@ -135,6 +135,15 @@ config AXP288_ADC
device. Depending on platform configuration, this general purpose ADC can
device. Depending on platform configuration, this general purpose ADC can
be used for sampling sensors such as thermal resistors.
be used for sampling sensors such as thermal resistors.
config DA9150_GPADC
tristate "Dialog DA9150 GPADC driver support"
depends on MFD_DA9150
help
Say yes here to build support for Dialog DA9150 GPADC.
This driver can also be built as a module. If chosen, the module name
will be da9150-gpadc.
config CC10001_ADC
config CC10001_ADC
tristate "Cosmic Circuits 10001 ADC driver"
tristate "Cosmic Circuits 10001 ADC driver"
depends on HAS_IOMEM || HAVE_CLK || REGULATOR
depends on HAS_IOMEM || HAVE_CLK || REGULATOR
...
...
drivers/iio/adc/Makefile
浏览文件 @
867fe7c3
...
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
...
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X)
+=
ad799x.o
obj-$(CONFIG_AD799X)
+=
ad799x.o
obj-$(CONFIG_AT91_ADC)
+=
at91_adc.o
obj-$(CONFIG_AT91_ADC)
+=
at91_adc.o
obj-$(CONFIG_AXP288_ADC)
+=
axp288_adc.o
obj-$(CONFIG_AXP288_ADC)
+=
axp288_adc.o
obj-$(CONFIG_DA9150_GPADC)
+=
da9150-gpadc.o
obj-$(CONFIG_CC10001_ADC)
+=
cc10001_adc.o
obj-$(CONFIG_CC10001_ADC)
+=
cc10001_adc.o
obj-$(CONFIG_EXYNOS_ADC)
+=
exynos_adc.o
obj-$(CONFIG_EXYNOS_ADC)
+=
exynos_adc.o
obj-$(CONFIG_LP8788_ADC)
+=
lp8788_adc.o
obj-$(CONFIG_LP8788_ADC)
+=
lp8788_adc.o
...
...
drivers/iio/adc/da9150-gpadc.c
0 → 100644
浏览文件 @
867fe7c3
/*
* DA9150 GPADC Driver
*
* Copyright (c) 2014 Dialog Semiconductor
*
* Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/mfd/da9150/core.h>
#include <linux/mfd/da9150/registers.h>
/* Channels */
enum
da9150_gpadc_hw_channel
{
DA9150_GPADC_HW_CHAN_GPIOA_2V
=
0
,
DA9150_GPADC_HW_CHAN_GPIOA_2V_
,
DA9150_GPADC_HW_CHAN_GPIOB_2V
,
DA9150_GPADC_HW_CHAN_GPIOB_2V_
,
DA9150_GPADC_HW_CHAN_GPIOC_2V
,
DA9150_GPADC_HW_CHAN_GPIOC_2V_
,
DA9150_GPADC_HW_CHAN_GPIOD_2V
,
DA9150_GPADC_HW_CHAN_GPIOD_2V_
,
DA9150_GPADC_HW_CHAN_IBUS_SENSE
,
DA9150_GPADC_HW_CHAN_IBUS_SENSE_
,
DA9150_GPADC_HW_CHAN_VBUS_DIV
,
DA9150_GPADC_HW_CHAN_VBUS_DIV_
,
DA9150_GPADC_HW_CHAN_ID
,
DA9150_GPADC_HW_CHAN_ID_
,
DA9150_GPADC_HW_CHAN_VSYS
,
DA9150_GPADC_HW_CHAN_VSYS_
,
DA9150_GPADC_HW_CHAN_GPIOA_6V
,
DA9150_GPADC_HW_CHAN_GPIOA_6V_
,
DA9150_GPADC_HW_CHAN_GPIOB_6V
,
DA9150_GPADC_HW_CHAN_GPIOB_6V_
,
DA9150_GPADC_HW_CHAN_GPIOC_6V
,
DA9150_GPADC_HW_CHAN_GPIOC_6V_
,
DA9150_GPADC_HW_CHAN_GPIOD_6V
,
DA9150_GPADC_HW_CHAN_GPIOD_6V_
,
DA9150_GPADC_HW_CHAN_VBAT
,
DA9150_GPADC_HW_CHAN_VBAT_
,
DA9150_GPADC_HW_CHAN_TBAT
,
DA9150_GPADC_HW_CHAN_TBAT_
,
DA9150_GPADC_HW_CHAN_TJUNC_CORE
,
DA9150_GPADC_HW_CHAN_TJUNC_CORE_
,
DA9150_GPADC_HW_CHAN_TJUNC_OVP
,
DA9150_GPADC_HW_CHAN_TJUNC_OVP_
,
};
enum
da9150_gpadc_channel
{
DA9150_GPADC_CHAN_GPIOA
=
0
,
DA9150_GPADC_CHAN_GPIOB
,
DA9150_GPADC_CHAN_GPIOC
,
DA9150_GPADC_CHAN_GPIOD
,
DA9150_GPADC_CHAN_IBUS
,
DA9150_GPADC_CHAN_VBUS
,
DA9150_GPADC_CHAN_VSYS
,
DA9150_GPADC_CHAN_VBAT
,
DA9150_GPADC_CHAN_TBAT
,
DA9150_GPADC_CHAN_TJUNC_CORE
,
DA9150_GPADC_CHAN_TJUNC_OVP
,
};
/* Private data */
struct
da9150_gpadc
{
struct
da9150
*
da9150
;
struct
device
*
dev
;
struct
mutex
lock
;
struct
completion
complete
;
};
static
irqreturn_t
da9150_gpadc_irq
(
int
irq
,
void
*
data
)
{
struct
da9150_gpadc
*
gpadc
=
data
;
complete
(
&
gpadc
->
complete
);
return
IRQ_HANDLED
;
}
static
int
da9150_gpadc_read_adc
(
struct
da9150_gpadc
*
gpadc
,
int
hw_chan
)
{
u8
result_regs
[
2
];
int
result
;
mutex_lock
(
&
gpadc
->
lock
);
/* Set channel & enable measurement */
da9150_reg_write
(
gpadc
->
da9150
,
DA9150_GPADC_MAN
,
(
DA9150_GPADC_EN_MASK
|
hw_chan
<<
DA9150_GPADC_MUX_SHIFT
));
/* Consume left-over completion from a previous timeout */
try_wait_for_completion
(
&
gpadc
->
complete
);
/* Check for actual completion */
wait_for_completion_timeout
(
&
gpadc
->
complete
,
msecs_to_jiffies
(
5
));
/* Read result and status from device */
da9150_bulk_read
(
gpadc
->
da9150
,
DA9150_GPADC_RES_A
,
2
,
result_regs
);
mutex_unlock
(
&
gpadc
->
lock
);
/* Check to make sure device really has completed reading */
if
(
result_regs
[
1
]
&
DA9150_GPADC_RUN_MASK
)
{
dev_err
(
gpadc
->
dev
,
"Timeout on channel %d of GPADC
\n
"
,
hw_chan
);
return
-
ETIMEDOUT
;
}
/* LSBs - 2 bits */
result
=
(
result_regs
[
1
]
&
DA9150_GPADC_RES_L_MASK
)
>>
DA9150_GPADC_RES_L_SHIFT
;
/* MSBs - 8 bits */
result
|=
result_regs
[
0
]
<<
DA9150_GPADC_RES_L_BITS
;
return
result
;
}
static
inline
int
da9150_gpadc_gpio_6v_voltage_now
(
int
raw_val
)
{
/* Convert to mV */
return
(
6
*
((
raw_val
*
1000
)
+
500
))
/
1024
;
}
static
inline
int
da9150_gpadc_ibus_current_avg
(
int
raw_val
)
{
/* Convert to mA */
return
(
4
*
((
raw_val
*
1000
)
+
500
))
/
2048
;
}
static
inline
int
da9150_gpadc_vbus_21v_voltage_now
(
int
raw_val
)
{
/* Convert to mV */
return
(
21
*
((
raw_val
*
1000
)
+
500
))
/
1024
;
}
static
inline
int
da9150_gpadc_vsys_6v_voltage_now
(
int
raw_val
)
{
/* Convert to mV */
return
(
3
*
((
raw_val
*
1000
)
+
500
))
/
512
;
}
static
int
da9150_gpadc_read_processed
(
struct
da9150_gpadc
*
gpadc
,
int
channel
,
int
hw_chan
,
int
*
val
)
{
int
raw_val
;
raw_val
=
da9150_gpadc_read_adc
(
gpadc
,
hw_chan
);
if
(
raw_val
<
0
)
return
raw_val
;
switch
(
channel
)
{
case
DA9150_GPADC_CHAN_GPIOA
:
case
DA9150_GPADC_CHAN_GPIOB
:
case
DA9150_GPADC_CHAN_GPIOC
:
case
DA9150_GPADC_CHAN_GPIOD
:
*
val
=
da9150_gpadc_gpio_6v_voltage_now
(
raw_val
);
break
;
case
DA9150_GPADC_CHAN_IBUS
:
*
val
=
da9150_gpadc_ibus_current_avg
(
raw_val
);
break
;
case
DA9150_GPADC_CHAN_VBUS
:
*
val
=
da9150_gpadc_vbus_21v_voltage_now
(
raw_val
);
break
;
case
DA9150_GPADC_CHAN_VSYS
:
*
val
=
da9150_gpadc_vsys_6v_voltage_now
(
raw_val
);
break
;
default:
/* No processing for other channels so return raw value */
*
val
=
raw_val
;
break
;
}
return
IIO_VAL_INT
;
}
static
int
da9150_gpadc_read_scale
(
int
channel
,
int
*
val
,
int
*
val2
)
{
switch
(
channel
)
{
case
DA9150_GPADC_CHAN_VBAT
:
*
val
=
2932
;
*
val2
=
1000
;
return
IIO_VAL_FRACTIONAL
;
case
DA9150_GPADC_CHAN_TJUNC_CORE
:
case
DA9150_GPADC_CHAN_TJUNC_OVP
:
*
val
=
1000000
;
*
val2
=
4420
;
return
IIO_VAL_FRACTIONAL
;
default:
return
-
EINVAL
;
}
}
static
int
da9150_gpadc_read_offset
(
int
channel
,
int
*
val
)
{
switch
(
channel
)
{
case
DA9150_GPADC_CHAN_VBAT
:
*
val
=
1500000
/
2932
;
return
IIO_VAL_INT
;
case
DA9150_GPADC_CHAN_TJUNC_CORE
:
case
DA9150_GPADC_CHAN_TJUNC_OVP
:
*
val
=
-
144
;
return
IIO_VAL_INT
;
default:
return
-
EINVAL
;
}
}
static
int
da9150_gpadc_read_raw
(
struct
iio_dev
*
indio_dev
,
struct
iio_chan_spec
const
*
chan
,
int
*
val
,
int
*
val2
,
long
mask
)
{
struct
da9150_gpadc
*
gpadc
=
iio_priv
(
indio_dev
);
if
((
chan
->
channel
<
DA9150_GPADC_CHAN_GPIOA
)
||
(
chan
->
channel
>
DA9150_GPADC_CHAN_TJUNC_OVP
))
return
-
EINVAL
;
switch
(
mask
)
{
case
IIO_CHAN_INFO_RAW
:
case
IIO_CHAN_INFO_PROCESSED
:
return
da9150_gpadc_read_processed
(
gpadc
,
chan
->
channel
,
chan
->
address
,
val
);
case
IIO_CHAN_INFO_SCALE
:
return
da9150_gpadc_read_scale
(
chan
->
channel
,
val
,
val2
);
case
IIO_CHAN_INFO_OFFSET
:
return
da9150_gpadc_read_offset
(
chan
->
channel
,
val
);
default:
return
-
EINVAL
;
}
}
static
const
struct
iio_info
da9150_gpadc_info
=
{
.
read_raw
=
&
da9150_gpadc_read_raw
,
.
driver_module
=
THIS_MODULE
,
};
#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info, \
_ext_name) { \
.type = _type, \
.indexed = 1, \
.channel = DA9150_GPADC_CHAN_##_id, \
.address = DA9150_GPADC_HW_CHAN_##_hw_id, \
.info_mask_separate = chan_info, \
.extend_name = _ext_name, \
.datasheet_name = #_id, \
}
#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name) \
DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
BIT(IIO_CHAN_INFO_RAW), _ext_name)
#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name) \
DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
_ext_name)
#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name) \
DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
/* Supported channels */
static
const
struct
iio_chan_spec
da9150_gpadc_channels
[]
=
{
DA9150_GPADC_CHANNEL_PROCESSED
(
GPIOA
,
GPIOA_6V
,
IIO_VOLTAGE
,
NULL
),
DA9150_GPADC_CHANNEL_PROCESSED
(
GPIOB
,
GPIOB_6V
,
IIO_VOLTAGE
,
NULL
),
DA9150_GPADC_CHANNEL_PROCESSED
(
GPIOC
,
GPIOC_6V
,
IIO_VOLTAGE
,
NULL
),
DA9150_GPADC_CHANNEL_PROCESSED
(
GPIOD
,
GPIOD_6V
,
IIO_VOLTAGE
,
NULL
),
DA9150_GPADC_CHANNEL_PROCESSED
(
IBUS
,
IBUS_SENSE
,
IIO_CURRENT
,
"ibus"
),
DA9150_GPADC_CHANNEL_PROCESSED
(
VBUS
,
VBUS_DIV_
,
IIO_VOLTAGE
,
"vbus"
),
DA9150_GPADC_CHANNEL_PROCESSED
(
VSYS
,
VSYS
,
IIO_VOLTAGE
,
"vsys"
),
DA9150_GPADC_CHANNEL_SCALED
(
VBAT
,
VBAT
,
IIO_VOLTAGE
,
"vbat"
),
DA9150_GPADC_CHANNEL_RAW
(
TBAT
,
TBAT
,
IIO_VOLTAGE
,
"tbat"
),
DA9150_GPADC_CHANNEL_SCALED
(
TJUNC_CORE
,
TJUNC_CORE
,
IIO_TEMP
,
"tjunc_core"
),
DA9150_GPADC_CHANNEL_SCALED
(
TJUNC_OVP
,
TJUNC_OVP
,
IIO_TEMP
,
"tjunc_ovp"
),
};
/* Default maps used by da9150-charger */
static
struct
iio_map
da9150_gpadc_default_maps
[]
=
{
{
.
consumer_dev_name
=
"da9150-charger"
,
.
consumer_channel
=
"CHAN_IBUS"
,
.
adc_channel_label
=
"IBUS"
,
},
{
.
consumer_dev_name
=
"da9150-charger"
,
.
consumer_channel
=
"CHAN_VBUS"
,
.
adc_channel_label
=
"VBUS"
,
},
{
.
consumer_dev_name
=
"da9150-charger"
,
.
consumer_channel
=
"CHAN_TJUNC"
,
.
adc_channel_label
=
"TJUNC_CORE"
,
},
{
.
consumer_dev_name
=
"da9150-charger"
,
.
consumer_channel
=
"CHAN_VBAT"
,
.
adc_channel_label
=
"VBAT"
,
},
{},
};
static
int
da9150_gpadc_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
da9150
*
da9150
=
dev_get_drvdata
(
dev
->
parent
);
struct
da9150_gpadc
*
gpadc
;
struct
iio_dev
*
indio_dev
;
int
irq
,
ret
;
indio_dev
=
devm_iio_device_alloc
(
dev
,
sizeof
(
*
gpadc
));
if
(
!
indio_dev
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to allocate IIO device
\n
"
);
return
-
ENOMEM
;
}
gpadc
=
iio_priv
(
indio_dev
);
platform_set_drvdata
(
pdev
,
indio_dev
);
gpadc
->
da9150
=
da9150
;
gpadc
->
dev
=
dev
;
mutex_init
(
&
gpadc
->
lock
);
init_completion
(
&
gpadc
->
complete
);
irq
=
platform_get_irq_byname
(
pdev
,
"GPADC"
);
if
(
irq
<
0
)
{
dev_err
(
dev
,
"Failed to get IRQ: %d
\n
"
,
irq
);
return
irq
;
}
ret
=
devm_request_threaded_irq
(
dev
,
irq
,
NULL
,
da9150_gpadc_irq
,
IRQF_ONESHOT
,
"GPADC"
,
gpadc
);
if
(
ret
)
{
dev_err
(
dev
,
"Failed to request IRQ %d: %d
\n
"
,
irq
,
ret
);
return
ret
;
}
ret
=
iio_map_array_register
(
indio_dev
,
da9150_gpadc_default_maps
);
if
(
ret
)
{
dev_err
(
dev
,
"Failed to register IIO maps: %d
\n
"
,
ret
);
return
ret
;
}
indio_dev
->
name
=
dev_name
(
dev
);
indio_dev
->
dev
.
parent
=
dev
;
indio_dev
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
indio_dev
->
info
=
&
da9150_gpadc_info
;
indio_dev
->
modes
=
INDIO_DIRECT_MODE
;
indio_dev
->
channels
=
da9150_gpadc_channels
;
indio_dev
->
num_channels
=
ARRAY_SIZE
(
da9150_gpadc_channels
);
ret
=
iio_device_register
(
indio_dev
);
if
(
ret
)
{
dev_err
(
dev
,
"Failed to register IIO device: %d
\n
"
,
ret
);
goto
iio_map_unreg
;
}
return
0
;
iio_map_unreg:
iio_map_array_unregister
(
indio_dev
);
return
ret
;
}
static
int
da9150_gpadc_remove
(
struct
platform_device
*
pdev
)
{
struct
iio_dev
*
indio_dev
=
platform_get_drvdata
(
pdev
);
iio_device_unregister
(
indio_dev
);
iio_map_array_unregister
(
indio_dev
);
return
0
;
}
static
struct
platform_driver
da9150_gpadc_driver
=
{
.
driver
=
{
.
name
=
"da9150-gpadc"
,
},
.
probe
=
da9150_gpadc_probe
,
.
remove
=
da9150_gpadc_remove
,
};
module_platform_driver
(
da9150_gpadc_driver
);
MODULE_DESCRIPTION
(
"GPADC Driver for DA9150"
);
MODULE_AUTHOR
(
"Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"
);
MODULE_LICENSE
(
"GPL"
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录