2010-09-13 18:05:04 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* Author : Mattias Wallin < mattias . wallin @ stericsson . com > for ST - Ericsson .
* License Terms : GNU General Public License v2
*/
2011-04-08 18:26:36 +04:00
/*
* AB8500 register access
* = = = = = = = = = = = = = = = = = = = = = =
*
* read :
* # echo BANK > < debugfs > / ab8500 / register - bank
* # echo ADDR > < debugfs > / ab8500 / register - address
* # cat < debugfs > / ab8500 / register - value
*
* write :
* # echo BANK > < debugfs > / ab8500 / register - bank
* # echo ADDR > < debugfs > / ab8500 / register - address
* # echo VALUE > < debugfs > / ab8500 / register - value
*
* read all registers from a bank :
* # echo BANK > < debugfs > / ab8500 / register - bank
* # cat < debugfs > / ab8500 / all - bank - register
*
* BANK target AB8500 register bank
* ADDR target AB8500 register address
* VALUE decimal or 0 x - prefixed hexadecimal
*
*
* User Space notification on AB8500 IRQ
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Allows user space entity to be notified when target AB8500 IRQ occurs .
* When subscribed , a sysfs entry is created in ab8500 . i2c platform device .
* One can pool this file to get target IRQ occurence information .
*
* subscribe to an AB8500 IRQ :
* # echo IRQ > < debugfs > / ab8500 / irq - subscribe
*
* unsubscribe from an AB8500 IRQ :
* # echo IRQ > < debugfs > / ab8500 / irq - unsubscribe
*
*
* AB8500 register formated read / write access
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Read : read data , data > > SHIFT , data & = MASK , output data
* [ 0xABCDEF98 ] shift = 12 mask = 0xFFF = > 0x00000CDE
* Write : read data , data & = ~ ( MASK < < SHIFT ) , data | = ( VALUE < < SHIFT ) , write data
* [ 0xABCDEF98 ] shift = 12 mask = 0xFFF value = 0x123 = > [ 0xAB123F98 ]
*
* Usage :
* # echo " CMD [OPTIONS] BANK ADRESS [VALUE] " > $ debugfs / ab8500 / hwreg
*
* CMD read read access
* write write access
*
* BANK target reg bank
* ADDRESS target reg address
* VALUE ( write ) value to be updated
*
* OPTIONS
* - d | - dec ( read ) output in decimal
* - h | - hexa ( read ) output in 0 x - hexa ( default )
* - l | - w | - b 32 bit ( default ) , 16 bit or 8 bit reg access
* - m | - mask MASK 0 x - hexa mask ( default 0xFFFFFFFF )
* - s | - shift SHIFT bit shift value ( read : left , write : right )
* - o | - offset OFFSET address offset to add to ADDRESS value
*
* Warning : bit shift operation is applied to bit - mask .
* Warning : bit shift direction depends on read or right command .
*/
2010-09-13 18:05:04 +04:00
# include <linux/seq_file.h>
# include <linux/uaccess.h>
# include <linux/fs.h>
2011-07-03 23:13:27 +04:00
# include <linux/module.h>
2010-09-13 18:05:04 +04:00
# include <linux/debugfs.h>
# include <linux/platform_device.h>
2013-01-14 20:10:36 +04:00
# include <linux/interrupt.h>
# include <linux/kobject.h>
# include <linux/slab.h>
2012-05-31 09:57:07 +04:00
# include <linux/irq.h>
2010-09-13 18:05:04 +04:00
# include <linux/mfd/abx500.h>
2013-02-07 02:23:01 +04:00
# include <linux/mfd/abx500/ab8500.h>
2011-05-31 16:54:27 +04:00
# include <linux/mfd/abx500/ab8500-gpadc.h>
2010-09-13 18:05:04 +04:00
2011-04-08 18:26:36 +04:00
# ifdef CONFIG_DEBUG_FS
# include <linux/string.h>
# include <linux/ctype.h>
# endif
2010-09-13 18:05:04 +04:00
static u32 debug_bank ;
static u32 debug_address ;
2013-04-12 19:02:09 +04:00
static int irq_ab8500 ;
2013-01-14 20:10:36 +04:00
static int irq_first ;
static int irq_last ;
2012-02-03 14:19:05 +04:00
static u32 * irq_count ;
static int num_irqs ;
2010-11-19 19:55:11 +03:00
2012-02-03 14:19:05 +04:00
static struct device_attribute * * dev_attr ;
static char * * event_name ;
2013-01-14 20:10:36 +04:00
2013-02-26 14:06:55 +04:00
static u8 avg_sample = SAMPLE_16 ;
static u8 trig_edge = RISING_EDGE ;
static u8 conv_type = ADC_SW ;
static u8 trig_timer ;
2010-09-13 18:05:04 +04:00
/**
* struct ab8500_reg_range
* @ first : the first address of the range
* @ last : the last address of the range
* @ perm : access permissions for the range
*/
struct ab8500_reg_range {
2010-11-26 15:06:39 +03:00
u8 first ;
u8 last ;
u8 perm ;
2010-09-13 18:05:04 +04:00
} ;
/**
2012-06-20 16:56:38 +04:00
* struct ab8500_prcmu_ranges
2010-09-13 18:05:04 +04:00
* @ num_ranges : the number of ranges in the list
* @ bankid : bank identifier
* @ range : the list of register ranges
*/
2012-06-20 16:56:38 +04:00
struct ab8500_prcmu_ranges {
2010-11-26 15:06:39 +03:00
u8 num_ranges ;
u8 bankid ;
const struct ab8500_reg_range * range ;
2010-09-13 18:05:04 +04:00
} ;
2011-04-08 18:26:36 +04:00
/* hwreg- "mask" and "shift" entries ressources */
struct hwreg_cfg {
u32 bank ; /* target bank */
u32 addr ; /* target address */
uint fmt ; /* format */
uint mask ; /* read/write mask, applied before any bit shift */
int shift ; /* bit shift (read:right shift, write:left shift */
} ;
/* fmt bit #0: 0=hexa, 1=dec */
# define REG_FMT_DEC(c) ((c)->fmt & 0x1)
# define REG_FMT_HEX(c) (!REG_FMT_DEC(c))
static struct hwreg_cfg hwreg_cfg = {
. addr = 0 , /* default: invalid phys addr */
. fmt = 0 , /* default: 32bit access, hex output */
. mask = 0xFFFFFFFF , /* default: no mask */
. shift = 0 , /* default: no bit shift */
} ;
2010-09-13 18:05:04 +04:00
# define AB8500_NAME_STRING "ab8500"
2011-05-31 16:54:27 +04:00
# define AB8500_ADC_NAME_STRING "gpadc"
2011-10-17 11:48:55 +04:00
# define AB8500_NUM_BANKS 24
2010-09-13 18:05:04 +04:00
# define AB8500_REV_REG 0x80
2012-07-06 18:11:50 +04:00
static struct ab8500_prcmu_ranges * debug_ranges ;
2013-08-23 16:07:42 +04:00
static struct ab8500_prcmu_ranges ab8500_debug_ranges [ AB8500_NUM_BANKS ] = {
2010-11-26 15:06:39 +03:00
[ 0x0 ] = {
. num_ranges = 0 ,
2013-01-14 21:17:34 +04:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ AB8500_SYS_CTRL1_BLOCK ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x02 ,
} ,
{
. first = 0x42 ,
. last = 0x42 ,
} ,
{
. first = 0x80 ,
. last = 0x81 ,
} ,
} ,
} ,
[ AB8500_SYS_CTRL2_BLOCK ] = {
. num_ranges = 4 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x0D ,
} ,
{
. first = 0x0F ,
. last = 0x17 ,
} ,
{
. first = 0x30 ,
. last = 0x30 ,
} ,
{
. first = 0x32 ,
. last = 0x33 ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL1 ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x03 ,
. last = 0x10 ,
} ,
{
. first = 0x80 ,
. last = 0x84 ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL2 ] = {
. num_ranges = 5 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x15 ,
} ,
{
. first = 0x17 ,
. last = 0x19 ,
} ,
{
. first = 0x1B ,
. last = 0x1D ,
} ,
{
. first = 0x1F ,
. last = 0x22 ,
} ,
{
. first = 0x40 ,
. last = 0x44 ,
} ,
/* 0x80-0x8B is SIM registers and should
* not be accessed from here */
} ,
} ,
[ AB8500_USB ] = {
. num_ranges = 2 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x80 ,
. last = 0x83 ,
} ,
{
. first = 0x87 ,
. last = 0x8A ,
} ,
} ,
} ,
[ AB8500_TVOUT ] = {
. num_ranges = 9 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x12 ,
} ,
{
. first = 0x15 ,
. last = 0x17 ,
} ,
{
. first = 0x19 ,
. last = 0x21 ,
} ,
{
. first = 0x27 ,
. last = 0x2C ,
} ,
{
. first = 0x41 ,
. last = 0x41 ,
} ,
{
. first = 0x45 ,
. last = 0x5B ,
} ,
{
. first = 0x5D ,
. last = 0x5D ,
} ,
{
. first = 0x69 ,
. last = 0x69 ,
} ,
{
. first = 0x80 ,
. last = 0x81 ,
} ,
} ,
} ,
[ AB8500_DBI ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ AB8500_ECI_AV_ACC ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x80 ,
. last = 0x82 ,
} ,
} ,
} ,
[ 0x9 ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ AB8500_GPADC ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x08 ,
} ,
} ,
} ,
[ AB8500_CHARGER ] = {
2011-10-17 11:48:55 +04:00
. num_ranges = 9 ,
2010-11-26 15:06:39 +03:00
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x03 ,
} ,
{
. first = 0x05 ,
. last = 0x05 ,
} ,
{
. first = 0x40 ,
. last = 0x40 ,
} ,
{
. first = 0x42 ,
. last = 0x42 ,
} ,
{
. first = 0x44 ,
. last = 0x44 ,
} ,
{
. first = 0x50 ,
. last = 0x55 ,
} ,
{
. first = 0x80 ,
. last = 0x82 ,
} ,
{
. first = 0xC0 ,
. last = 0xC2 ,
} ,
2011-10-17 11:48:55 +04:00
{
. first = 0xf5 ,
2012-07-06 18:11:50 +04:00
. last = 0xf6 ,
2011-10-17 11:48:55 +04:00
} ,
2010-11-26 15:06:39 +03:00
} ,
} ,
[ AB8500_GAS_GAUGE ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x07 ,
. last = 0x0A ,
} ,
{
. first = 0x10 ,
. last = 0x14 ,
} ,
} ,
} ,
2011-10-17 11:48:55 +04:00
[ AB8500_DEVELOPMENT ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
} ,
} ,
[ AB8500_DEBUG ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x05 ,
. last = 0x07 ,
} ,
} ,
} ,
2010-11-26 15:06:39 +03:00
[ AB8500_AUDIO ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x6F ,
} ,
} ,
} ,
[ AB8500_INTERRUPT ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ AB8500_RTC ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x0F ,
} ,
} ,
} ,
[ AB8500_MISC ] = {
. num_ranges = 8 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x05 ,
} ,
{
. first = 0x10 ,
. last = 0x15 ,
} ,
{
. first = 0x20 ,
. last = 0x25 ,
} ,
{
. first = 0x30 ,
. last = 0x35 ,
} ,
{
. first = 0x40 ,
. last = 0x45 ,
} ,
{
. first = 0x50 ,
. last = 0x50 ,
} ,
{
. first = 0x60 ,
. last = 0x67 ,
} ,
{
. first = 0x80 ,
. last = 0x80 ,
} ,
} ,
} ,
[ 0x11 ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ 0x12 ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ 0x13 ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ 0x14 ] = {
. num_ranges = 0 ,
2010-12-13 17:06:47 +03:00
. range = NULL ,
2010-11-26 15:06:39 +03:00
} ,
[ AB8500_OTP_EMUL ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x01 ,
. last = 0x0F ,
} ,
} ,
} ,
2010-09-13 18:05:04 +04:00
} ;
2013-08-23 16:07:42 +04:00
static struct ab8500_prcmu_ranges ab8505_debug_ranges [ AB8500_NUM_BANKS ] = {
2012-07-06 18:11:50 +04:00
[ 0x0 ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_SYS_CTRL1_BLOCK ] = {
. num_ranges = 5 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x04 ,
} ,
{
. first = 0x42 ,
. last = 0x42 ,
} ,
{
. first = 0x52 ,
. last = 0x52 ,
} ,
{
. first = 0x54 ,
. last = 0x57 ,
} ,
{
. first = 0x80 ,
. last = 0x83 ,
} ,
} ,
} ,
[ AB8500_SYS_CTRL2_BLOCK ] = {
. num_ranges = 5 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x0D ,
} ,
{
. first = 0x0F ,
. last = 0x17 ,
} ,
{
. first = 0x20 ,
. last = 0x20 ,
} ,
{
. first = 0x30 ,
. last = 0x30 ,
} ,
{
. first = 0x32 ,
. last = 0x3A ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL1 ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x03 ,
. last = 0x11 ,
} ,
{
. first = 0x80 ,
. last = 0x86 ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL2 ] = {
. num_ranges = 6 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x06 ,
} ,
{
. first = 0x08 ,
. last = 0x15 ,
} ,
{
. first = 0x17 ,
. last = 0x19 ,
} ,
{
. first = 0x1B ,
. last = 0x1D ,
} ,
{
. first = 0x1F ,
. last = 0x30 ,
} ,
{
. first = 0x40 ,
. last = 0x48 ,
} ,
/* 0x80-0x8B is SIM registers and should
* not be accessed from here */
} ,
} ,
[ AB8500_USB ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x80 ,
. last = 0x83 ,
} ,
{
. first = 0x87 ,
. last = 0x8A ,
} ,
{
. first = 0x91 ,
. last = 0x94 ,
} ,
} ,
} ,
[ AB8500_TVOUT ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_DBI ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_ECI_AV_ACC ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x80 ,
. last = 0x82 ,
} ,
} ,
} ,
[ AB8500_RESERVED ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_GPADC ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x08 ,
} ,
} ,
} ,
[ AB8500_CHARGER ] = {
. num_ranges = 9 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x02 ,
. last = 0x03 ,
} ,
{
. first = 0x05 ,
. last = 0x05 ,
} ,
{
. first = 0x40 ,
. last = 0x44 ,
} ,
{
. first = 0x50 ,
. last = 0x57 ,
} ,
{
. first = 0x60 ,
. last = 0x60 ,
} ,
{
. first = 0xA0 ,
. last = 0xA7 ,
} ,
{
. first = 0xAF ,
. last = 0xB2 ,
} ,
{
. first = 0xC0 ,
. last = 0xC2 ,
} ,
{
. first = 0xF5 ,
. last = 0xF5 ,
} ,
} ,
} ,
[ AB8500_GAS_GAUGE ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x07 ,
. last = 0x0A ,
} ,
{
. first = 0x10 ,
. last = 0x14 ,
} ,
} ,
} ,
[ AB8500_AUDIO ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x83 ,
} ,
} ,
} ,
[ AB8500_INTERRUPT ] = {
. num_ranges = 11 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x04 ,
} ,
{
. first = 0x06 ,
. last = 0x07 ,
} ,
{
. first = 0x09 ,
. last = 0x09 ,
} ,
{
. first = 0x0B ,
. last = 0x0C ,
} ,
{
. first = 0x12 ,
. last = 0x15 ,
} ,
{
. first = 0x18 ,
. last = 0x18 ,
} ,
/* Latch registers should not be read here */
{
. first = 0x40 ,
. last = 0x44 ,
} ,
{
. first = 0x46 ,
. last = 0x49 ,
} ,
{
. first = 0x4B ,
. last = 0x4D ,
} ,
{
. first = 0x52 ,
. last = 0x55 ,
} ,
{
. first = 0x58 ,
. last = 0x58 ,
} ,
/* LatchHier registers should not be read here */
} ,
} ,
[ AB8500_RTC ] = {
. num_ranges = 2 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x14 ,
} ,
{
. first = 0x16 ,
. last = 0x17 ,
} ,
} ,
} ,
[ AB8500_MISC ] = {
. num_ranges = 8 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x06 ,
} ,
{
. first = 0x10 ,
. last = 0x16 ,
} ,
{
. first = 0x20 ,
. last = 0x26 ,
} ,
{
. first = 0x30 ,
. last = 0x36 ,
} ,
{
. first = 0x40 ,
. last = 0x46 ,
} ,
{
. first = 0x50 ,
. last = 0x50 ,
} ,
{
. first = 0x60 ,
. last = 0x6B ,
} ,
{
. first = 0x80 ,
. last = 0x82 ,
} ,
} ,
} ,
[ AB8500_DEVELOPMENT ] = {
. num_ranges = 2 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x05 ,
. last = 0x05 ,
} ,
} ,
} ,
[ AB8500_DEBUG ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x05 ,
. last = 0x07 ,
} ,
} ,
} ,
[ AB8500_PROD_TEST ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_STE_TEST ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_OTP_EMUL ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x01 ,
. last = 0x15 ,
} ,
} ,
} ,
} ;
2013-08-23 16:07:42 +04:00
static struct ab8500_prcmu_ranges ab8540_debug_ranges [ AB8500_NUM_BANKS ] = {
2012-11-19 15:20:03 +04:00
[ AB8500_M_FSM_RANK ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x0B ,
} ,
} ,
} ,
[ AB8500_SYS_CTRL1_BLOCK ] = {
. num_ranges = 6 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x04 ,
} ,
{
. first = 0x42 ,
. last = 0x42 ,
} ,
{
. first = 0x50 ,
. last = 0x54 ,
} ,
{
. first = 0x57 ,
. last = 0x57 ,
} ,
{
. first = 0x80 ,
. last = 0x83 ,
} ,
{
. first = 0x90 ,
. last = 0x90 ,
} ,
} ,
} ,
[ AB8500_SYS_CTRL2_BLOCK ] = {
. num_ranges = 5 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x0D ,
} ,
{
. first = 0x0F ,
. last = 0x10 ,
} ,
{
. first = 0x20 ,
. last = 0x21 ,
} ,
{
. first = 0x32 ,
. last = 0x3C ,
} ,
{
. first = 0x40 ,
. last = 0x42 ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL1 ] = {
. num_ranges = 4 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x03 ,
. last = 0x15 ,
} ,
{
. first = 0x20 ,
. last = 0x20 ,
} ,
{
. first = 0x80 ,
. last = 0x85 ,
} ,
{
. first = 0x87 ,
. last = 0x88 ,
} ,
} ,
} ,
[ AB8500_REGU_CTRL2 ] = {
. num_ranges = 8 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x06 ,
} ,
{
. first = 0x08 ,
. last = 0x15 ,
} ,
{
. first = 0x17 ,
. last = 0x19 ,
} ,
{
. first = 0x1B ,
. last = 0x1D ,
} ,
{
. first = 0x1F ,
. last = 0x2F ,
} ,
{
. first = 0x31 ,
. last = 0x3A ,
} ,
{
. first = 0x43 ,
. last = 0x44 ,
} ,
{
. first = 0x48 ,
. last = 0x49 ,
} ,
} ,
} ,
[ AB8500_USB ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x80 ,
. last = 0x83 ,
} ,
{
. first = 0x87 ,
. last = 0x8A ,
} ,
{
. first = 0x91 ,
. last = 0x94 ,
} ,
} ,
} ,
[ AB8500_TVOUT ] = {
. num_ranges = 0 ,
. range = NULL
} ,
[ AB8500_DBI ] = {
. num_ranges = 4 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x07 ,
} ,
{
. first = 0x10 ,
. last = 0x11 ,
} ,
{
. first = 0x20 ,
. last = 0x21 ,
} ,
{
. first = 0x30 ,
. last = 0x43 ,
} ,
} ,
} ,
[ AB8500_ECI_AV_ACC ] = {
. num_ranges = 2 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x03 ,
} ,
{
. first = 0x80 ,
. last = 0x82 ,
} ,
} ,
} ,
[ AB8500_RESERVED ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_GPADC ] = {
. num_ranges = 4 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x01 ,
} ,
{
. first = 0x04 ,
. last = 0x06 ,
} ,
{
. first = 0x09 ,
. last = 0x0A ,
} ,
{
. first = 0x10 ,
. last = 0x14 ,
} ,
} ,
} ,
[ AB8500_CHARGER ] = {
. num_ranges = 10 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x02 ,
. last = 0x05 ,
} ,
{
. first = 0x40 ,
. last = 0x44 ,
} ,
{
. first = 0x50 ,
. last = 0x57 ,
} ,
{
. first = 0x60 ,
. last = 0x60 ,
} ,
{
. first = 0x70 ,
. last = 0x70 ,
} ,
{
. first = 0xA0 ,
. last = 0xA9 ,
} ,
{
. first = 0xAF ,
. last = 0xB2 ,
} ,
{
. first = 0xC0 ,
. last = 0xC6 ,
} ,
{
. first = 0xF5 ,
. last = 0xF5 ,
} ,
} ,
} ,
[ AB8500_GAS_GAUGE ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x00 ,
} ,
{
. first = 0x07 ,
. last = 0x0A ,
} ,
{
. first = 0x10 ,
. last = 0x14 ,
} ,
} ,
} ,
[ AB8500_AUDIO ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x9f ,
} ,
} ,
} ,
[ AB8500_INTERRUPT ] = {
. num_ranges = 6 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x05 ,
} ,
{
. first = 0x0B ,
. last = 0x0D ,
} ,
{
. first = 0x12 ,
. last = 0x20 ,
} ,
/* Latch registers should not be read here */
{
. first = 0x40 ,
. last = 0x45 ,
} ,
{
. first = 0x4B ,
. last = 0x4D ,
} ,
{
. first = 0x52 ,
. last = 0x60 ,
} ,
/* LatchHier registers should not be read here */
} ,
} ,
[ AB8500_RTC ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x07 ,
} ,
{
. first = 0x0B ,
. last = 0x18 ,
} ,
{
. first = 0x20 ,
. last = 0x25 ,
} ,
} ,
} ,
[ AB8500_MISC ] = {
. num_ranges = 9 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x06 ,
} ,
{
. first = 0x10 ,
. last = 0x16 ,
} ,
{
. first = 0x20 ,
. last = 0x26 ,
} ,
{
. first = 0x30 ,
. last = 0x36 ,
} ,
{
. first = 0x40 ,
. last = 0x49 ,
} ,
{
. first = 0x50 ,
. last = 0x50 ,
} ,
{
. first = 0x60 ,
. last = 0x6B ,
} ,
{
. first = 0x70 ,
. last = 0x74 ,
} ,
{
. first = 0x80 ,
. last = 0x82 ,
} ,
} ,
} ,
[ AB8500_DEVELOPMENT ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x01 ,
} ,
{
. first = 0x06 ,
. last = 0x06 ,
} ,
{
. first = 0x10 ,
. last = 0x21 ,
} ,
} ,
} ,
[ AB8500_DEBUG ] = {
. num_ranges = 3 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x01 ,
. last = 0x0C ,
} ,
{
. first = 0x0E ,
. last = 0x11 ,
} ,
{
. first = 0x80 ,
. last = 0x81 ,
} ,
} ,
} ,
[ AB8500_PROD_TEST ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_STE_TEST ] = {
. num_ranges = 0 ,
. range = NULL ,
} ,
[ AB8500_OTP_EMUL ] = {
. num_ranges = 1 ,
. range = ( struct ab8500_reg_range [ ] ) {
{
. first = 0x00 ,
. last = 0x3F ,
} ,
} ,
} ,
} ;
2013-01-14 20:10:36 +04:00
static irqreturn_t ab8500_debug_handler ( int irq , void * data )
{
char buf [ 16 ] ;
struct kobject * kobj = ( struct kobject * ) data ;
2010-11-19 19:55:11 +03:00
unsigned int irq_abb = irq - irq_first ;
2013-01-14 20:10:36 +04:00
2012-02-03 14:19:05 +04:00
if ( irq_abb < num_irqs )
2010-11-19 19:55:11 +03:00
irq_count [ irq_abb ] + + ;
2013-01-14 20:10:36 +04:00
/*
* This makes it possible to use poll for events ( POLLPRI | POLLERR )
2010-11-19 19:55:11 +03:00
* from userspace on sysfs file named < irq - nr >
2013-01-14 20:10:36 +04:00
*/
2010-11-19 19:55:11 +03:00
sprintf ( buf , " %d " , irq ) ;
2013-01-14 20:10:36 +04:00
sysfs_notify ( kobj , NULL , buf ) ;
return IRQ_HANDLED ;
}
2012-01-26 18:39:20 +04:00
/* Prints to seq_file or log_buf */
static int ab8500_registers_print ( struct device * dev , u32 bank ,
struct seq_file * s )
2010-09-13 18:05:04 +04:00
{
2010-11-26 15:06:39 +03:00
unsigned int i ;
for ( i = 0 ; i < debug_ranges [ bank ] . num_ranges ; i + + ) {
u32 reg ;
for ( reg = debug_ranges [ bank ] . range [ i ] . first ;
reg < = debug_ranges [ bank ] . range [ i ] . last ;
reg + + ) {
u8 value ;
int err ;
err = abx500_get_register_interruptible ( dev ,
( u8 ) bank , ( u8 ) reg , & value ) ;
if ( err < 0 ) {
dev_err ( dev , " ab->read fail %d \n " , err ) ;
return err ;
}
2012-01-26 18:39:20 +04:00
if ( s ) {
2012-05-28 17:53:58 +04:00
err = seq_printf ( s , " [0x%02X/0x%02X]: 0x%02X \n " ,
2012-01-26 18:39:20 +04:00
bank , reg , value ) ;
if ( err < 0 ) {
/* Error is not returned here since
* the output is wanted in any case */
return 0 ;
}
} else {
2012-05-28 17:53:58 +04:00
printk ( KERN_INFO " [0x%02X/0x%02X]: 0x%02X \n " ,
bank , reg , value ) ;
2010-11-26 15:06:39 +03:00
}
}
}
return 0 ;
2010-09-13 18:05:04 +04:00
}
2012-01-26 18:39:20 +04:00
static int ab8500_print_bank_registers ( struct seq_file * s , void * p )
{
struct device * dev = s - > private ;
u32 bank = debug_bank ;
seq_printf ( s , AB8500_NAME_STRING " register values: \n " ) ;
2012-05-28 17:53:58 +04:00
seq_printf ( s , " bank 0x%02X: \n " , bank ) ;
2012-01-26 18:39:20 +04:00
ab8500_registers_print ( dev , bank , s ) ;
return 0 ;
}
2010-09-13 18:05:04 +04:00
static int ab8500_registers_open ( struct inode * inode , struct file * file )
{
2012-01-26 18:39:20 +04:00
return single_open ( file , ab8500_print_bank_registers , inode - > i_private ) ;
2010-09-13 18:05:04 +04:00
}
static const struct file_operations ab8500_registers_fops = {
2010-11-26 15:06:39 +03:00
. open = ab8500_registers_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
2010-09-13 18:05:04 +04:00
} ;
2012-01-26 18:39:20 +04:00
static int ab8500_print_all_banks ( struct seq_file * s , void * p )
{
struct device * dev = s - > private ;
unsigned int i ;
int err ;
seq_printf ( s , AB8500_NAME_STRING " register values: \n " ) ;
2012-11-19 15:20:03 +04:00
for ( i = 0 ; i < AB8500_NUM_BANKS ; i + + ) {
2012-05-28 17:53:58 +04:00
err = seq_printf ( s , " bank 0x%02X: \n " , i ) ;
2012-01-26 18:39:20 +04:00
ab8500_registers_print ( dev , i , s ) ;
}
return 0 ;
}
2012-01-27 14:35:41 +04:00
/* Dump registers to kernel log */
void ab8500_dump_all_banks ( struct device * dev )
{
unsigned int i ;
printk ( KERN_INFO " ab8500 register values: \n " ) ;
for ( i = 1 ; i < AB8500_NUM_BANKS ; i + + ) {
2012-05-28 17:53:58 +04:00
printk ( KERN_INFO " bank 0x%02X: \n " , i ) ;
2012-01-27 14:35:41 +04:00
ab8500_registers_print ( dev , i , NULL ) ;
}
}
2013-02-12 18:35:28 +04:00
/* Space for 500 registers. */
# define DUMP_MAX_REGS 700
2013-08-23 16:07:42 +04:00
static struct ab8500_register_dump
2013-02-12 18:35:28 +04:00
{
u8 bank ;
u8 reg ;
u8 value ;
} ab8500_complete_register_dump [ DUMP_MAX_REGS ] ;
extern int prcmu_abb_read ( u8 slave , u8 reg , u8 * value , u8 size ) ;
/* This shall only be called upon kernel panic! */
void ab8500_dump_all_banks_to_mem ( void )
{
int i , r = 0 ;
u8 bank ;
2012-06-18 12:35:28 +04:00
int err = 0 ;
2013-02-12 18:35:28 +04:00
pr_info ( " Saving all ABB registers at \" ab8500_complete_register_dump \" "
" for crash analyze. \n " ) ;
2012-11-19 15:20:03 +04:00
for ( bank = 0 ; bank < AB8500_NUM_BANKS ; bank + + ) {
2013-02-12 18:35:28 +04:00
for ( i = 0 ; i < debug_ranges [ bank ] . num_ranges ; i + + ) {
u8 reg ;
for ( reg = debug_ranges [ bank ] . range [ i ] . first ;
reg < = debug_ranges [ bank ] . range [ i ] . last ;
reg + + ) {
u8 value ;
err = prcmu_abb_read ( bank , reg , & value , 1 ) ;
2012-06-18 12:35:28 +04:00
if ( err < 0 )
goto out ;
2013-02-12 18:35:28 +04:00
ab8500_complete_register_dump [ r ] . bank = bank ;
ab8500_complete_register_dump [ r ] . reg = reg ;
ab8500_complete_register_dump [ r ] . value = value ;
r + + ;
if ( r > = DUMP_MAX_REGS ) {
pr_err ( " %s: too many register to dump! \n " ,
__func__ ) ;
2012-06-18 12:35:28 +04:00
err = - EINVAL ;
goto out ;
2013-02-12 18:35:28 +04:00
}
}
}
}
2012-06-18 12:35:28 +04:00
out :
if ( err > = 0 )
pr_info ( " Saved all ABB registers. \n " ) ;
else
pr_info ( " Failed to save all ABB registers. \n " ) ;
2013-02-12 18:35:28 +04:00
}
2012-01-26 18:39:20 +04:00
static int ab8500_all_banks_open ( struct inode * inode , struct file * file )
{
struct seq_file * s ;
int err ;
err = single_open ( file , ab8500_print_all_banks , inode - > i_private ) ;
if ( ! err ) {
/* Default buf size in seq_read is not enough */
s = ( struct seq_file * ) file - > private_data ;
s - > size = ( PAGE_SIZE * 2 ) ;
s - > buf = kmalloc ( s - > size , GFP_KERNEL ) ;
if ( ! s - > buf ) {
single_release ( inode , file ) ;
err = - ENOMEM ;
}
}
return err ;
}
static const struct file_operations ab8500_all_banks_fops = {
. open = ab8500_all_banks_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2010-09-13 18:05:04 +04:00
static int ab8500_bank_print ( struct seq_file * s , void * p )
{
2012-05-28 17:53:58 +04:00
return seq_printf ( s , " 0x%02X \n " , debug_bank ) ;
2010-09-13 18:05:04 +04:00
}
static int ab8500_bank_open ( struct inode * inode , struct file * file )
{
2010-11-26 15:06:39 +03:00
return single_open ( file , ab8500_bank_print , inode - > i_private ) ;
2010-09-13 18:05:04 +04:00
}
static ssize_t ab8500_bank_write ( struct file * file ,
2010-11-26 15:06:39 +03:00
const char __user * user_buf ,
size_t count , loff_t * ppos )
2010-09-13 18:05:04 +04:00
{
2010-11-26 15:06:39 +03:00
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_bank ;
int err ;
2011-06-07 00:43:32 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_bank ) ;
2010-11-26 15:06:39 +03:00
if ( err )
2011-06-07 00:43:32 +04:00
return err ;
2010-11-26 15:06:39 +03:00
if ( user_bank > = AB8500_NUM_BANKS ) {
dev_err ( dev , " debugfs error input > number of banks \n " ) ;
return - EINVAL ;
}
debug_bank = user_bank ;
2011-06-07 00:43:32 +04:00
return count ;
2010-09-13 18:05:04 +04:00
}
static int ab8500_address_print ( struct seq_file * s , void * p )
{
2010-11-26 15:06:39 +03:00
return seq_printf ( s , " 0x%02X \n " , debug_address ) ;
2010-09-13 18:05:04 +04:00
}
static int ab8500_address_open ( struct inode * inode , struct file * file )
{
2010-11-26 15:06:39 +03:00
return single_open ( file , ab8500_address_print , inode - > i_private ) ;
2010-09-13 18:05:04 +04:00
}
static ssize_t ab8500_address_write ( struct file * file ,
2013-02-26 16:05:15 +04:00
const char __user * user_buf ,
size_t count , loff_t * ppos )
2010-09-13 18:05:04 +04:00
{
2010-11-26 15:06:39 +03:00
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_address ;
int err ;
2011-06-07 00:43:32 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_address ) ;
2010-11-26 15:06:39 +03:00
if ( err )
2011-06-07 00:43:32 +04:00
return err ;
2010-11-26 15:06:39 +03:00
if ( user_address > 0xff ) {
dev_err ( dev , " debugfs error input > 0xff \n " ) ;
return - EINVAL ;
}
debug_address = user_address ;
2012-11-23 13:41:00 +04:00
2011-06-07 00:43:32 +04:00
return count ;
2010-09-13 18:05:04 +04:00
}
static int ab8500_val_print ( struct seq_file * s , void * p )
{
2010-11-26 15:06:39 +03:00
struct device * dev = s - > private ;
int ret ;
u8 regvalue ;
ret = abx500_get_register_interruptible ( dev ,
( u8 ) debug_bank , ( u8 ) debug_address , & regvalue ) ;
if ( ret < 0 ) {
dev_err ( dev , " abx500_get_reg fail %d, %d \n " ,
ret , __LINE__ ) ;
return - EINVAL ;
}
seq_printf ( s , " 0x%02X \n " , regvalue ) ;
return 0 ;
2010-09-13 18:05:04 +04:00
}
static int ab8500_val_open ( struct inode * inode , struct file * file )
{
2010-11-26 15:06:39 +03:00
return single_open ( file , ab8500_val_print , inode - > i_private ) ;
2010-09-13 18:05:04 +04:00
}
static ssize_t ab8500_val_write ( struct file * file ,
2013-02-26 16:05:15 +04:00
const char __user * user_buf ,
size_t count , loff_t * ppos )
2010-09-13 18:05:04 +04:00
{
2010-11-26 15:06:39 +03:00
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_val ;
int err ;
2011-06-07 00:43:32 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_val ) ;
2010-11-26 15:06:39 +03:00
if ( err )
2011-06-07 00:43:32 +04:00
return err ;
2010-11-26 15:06:39 +03:00
if ( user_val > 0xff ) {
dev_err ( dev , " debugfs error input > 0xff \n " ) ;
return - EINVAL ;
}
err = abx500_set_register_interruptible ( dev ,
( u8 ) debug_bank , debug_address , ( u8 ) user_val ) ;
if ( err < 0 ) {
printk ( KERN_ERR " abx500_set_reg failed %d, %d " , err , __LINE__ ) ;
return - EINVAL ;
}
2011-06-07 00:43:32 +04:00
return count ;
2010-09-13 18:05:04 +04:00
}
2012-02-14 16:01:00 +04:00
/*
* Interrupt status
*/
static u32 num_interrupts [ AB8500_MAX_NR_IRQS ] ;
2012-05-31 09:57:07 +04:00
static u32 num_wake_interrupts [ AB8500_MAX_NR_IRQS ] ;
2012-02-14 16:01:00 +04:00
static int num_interrupt_lines ;
2012-05-31 09:57:07 +04:00
bool __attribute__ ( ( weak ) ) suspend_test_wake_cause_interrupt_is_mine ( u32 my_int )
{
return false ;
}
2012-02-14 16:01:00 +04:00
void ab8500_debug_register_interrupt ( int line )
{
2012-05-31 09:57:07 +04:00
if ( line < num_interrupt_lines ) {
2012-02-14 16:01:00 +04:00
num_interrupts [ line ] + + ;
2013-04-12 19:02:09 +04:00
if ( suspend_test_wake_cause_interrupt_is_mine ( irq_ab8500 ) )
2012-05-31 09:57:07 +04:00
num_wake_interrupts [ line ] + + ;
}
2012-02-14 16:01:00 +04:00
}
static int ab8500_interrupts_print ( struct seq_file * s , void * p )
{
int line ;
2012-05-31 09:57:07 +04:00
seq_printf ( s , " name: number: number of: wake: \n " ) ;
for ( line = 0 ; line < num_interrupt_lines ; line + + ) {
struct irq_desc * desc = irq_to_desc ( line + irq_first ) ;
struct irqaction * action = desc - > action ;
2012-02-14 16:01:00 +04:00
2012-05-31 09:57:07 +04:00
seq_printf ( s , " %3i: %6i %4i " , line ,
num_interrupts [ line ] ,
num_wake_interrupts [ line ] ) ;
if ( desc & & desc - > name )
seq_printf ( s , " -%-8s " , desc - > name ) ;
if ( action ) {
seq_printf ( s , " %s " , action - > name ) ;
while ( ( action = action - > next ) ! = NULL )
seq_printf ( s , " , %s " , action - > name ) ;
}
seq_putc ( s , ' \n ' ) ;
}
2012-02-14 16:01:00 +04:00
return 0 ;
}
static int ab8500_interrupts_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_interrupts_print , inode - > i_private ) ;
}
2011-04-08 18:26:36 +04:00
/*
* - HWREG DB8500 formated routines
*/
static int ab8500_hwreg_print ( struct seq_file * s , void * d )
{
struct device * dev = s - > private ;
int ret ;
u8 regvalue ;
ret = abx500_get_register_interruptible ( dev ,
( u8 ) hwreg_cfg . bank , ( u8 ) hwreg_cfg . addr , & regvalue ) ;
if ( ret < 0 ) {
dev_err ( dev , " abx500_get_reg fail %d, %d \n " ,
ret , __LINE__ ) ;
return - EINVAL ;
}
if ( hwreg_cfg . shift > = 0 )
regvalue > > = hwreg_cfg . shift ;
else
regvalue < < = - hwreg_cfg . shift ;
regvalue & = hwreg_cfg . mask ;
if ( REG_FMT_DEC ( & hwreg_cfg ) )
seq_printf ( s , " %d \n " , regvalue ) ;
else
seq_printf ( s , " 0x%02X \n " , regvalue ) ;
return 0 ;
}
static int ab8500_hwreg_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_hwreg_print , inode - > i_private ) ;
}
2013-02-26 18:03:33 +04:00
# define AB8500_SUPPLY_CONTROL_CONFIG_1 0x01
# define AB8500_SUPPLY_CONTROL_REG 0x00
# define AB8500_FIRST_SIM_REG 0x80
# define AB8500_LAST_SIM_REG 0x8B
# define AB8505_LAST_SIM_REG 0x8C
static int ab8500_print_modem_registers ( struct seq_file * s , void * p )
{
struct device * dev = s - > private ;
struct ab8500 * ab8500 ;
int err ;
u8 value ;
u8 orig_value ;
u32 bank = AB8500_REGU_CTRL2 ;
u32 last_sim_reg = AB8500_LAST_SIM_REG ;
u32 reg ;
ab8500 = dev_get_drvdata ( dev - > parent ) ;
dev_warn ( dev , " WARNING! This operation can interfer with modem side \n "
" and should only be done with care \n " ) ;
err = abx500_get_register_interruptible ( dev ,
AB8500_REGU_CTRL1 , AB8500_SUPPLY_CONTROL_REG , & orig_value ) ;
if ( err < 0 ) {
dev_err ( dev , " ab->read fail %d \n " , err ) ;
return err ;
}
/* Config 1 will allow APE side to read SIM registers */
err = abx500_set_register_interruptible ( dev ,
AB8500_REGU_CTRL1 , AB8500_SUPPLY_CONTROL_REG ,
AB8500_SUPPLY_CONTROL_CONFIG_1 ) ;
if ( err < 0 ) {
dev_err ( dev , " ab->write fail %d \n " , err ) ;
return err ;
}
seq_printf ( s , " bank 0x%02X: \n " , bank ) ;
if ( is_ab9540 ( ab8500 ) | | is_ab8505 ( ab8500 ) )
last_sim_reg = AB8505_LAST_SIM_REG ;
for ( reg = AB8500_FIRST_SIM_REG ; reg < = last_sim_reg ; reg + + ) {
err = abx500_get_register_interruptible ( dev ,
bank , reg , & value ) ;
if ( err < 0 ) {
dev_err ( dev , " ab->read fail %d \n " , err ) ;
return err ;
}
err = seq_printf ( s , " [0x%02X/0x%02X]: 0x%02X \n " ,
bank , reg , value ) ;
}
err = abx500_set_register_interruptible ( dev ,
AB8500_REGU_CTRL1 , AB8500_SUPPLY_CONTROL_REG , orig_value ) ;
if ( err < 0 ) {
dev_err ( dev , " ab->write fail %d \n " , err ) ;
return err ;
}
return 0 ;
}
static int ab8500_modem_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_print_modem_registers , inode - > i_private ) ;
}
static const struct file_operations ab8500_modem_fops = {
. open = ab8500_modem_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2011-05-31 16:54:27 +04:00
static int ab8500_gpadc_bat_ctrl_print ( struct seq_file * s , void * p )
{
int bat_ctrl_raw ;
int bat_ctrl_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
bat_ctrl_raw = ab8500_gpadc_read_raw ( gpadc , BAT_CTRL ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
bat_ctrl_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
BAT_CTRL , bat_ctrl_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
bat_ctrl_convert , bat_ctrl_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_bat_ctrl_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_bat_ctrl_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
. open = ab8500_gpadc_bat_ctrl_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_btemp_ball_print ( struct seq_file * s , void * p )
{
int btemp_ball_raw ;
int btemp_ball_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
btemp_ball_raw = ab8500_gpadc_read_raw ( gpadc , BTEMP_BALL ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
btemp_ball_convert = ab8500_gpadc_ad_to_voltage ( gpadc , BTEMP_BALL ,
2013-02-26 14:06:55 +04:00
btemp_ball_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s ,
2013-02-26 16:05:15 +04:00
" %d,0x%X \n " , btemp_ball_convert , btemp_ball_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_btemp_ball_open ( struct inode * inode ,
2013-02-26 16:05:15 +04:00
struct file * file )
2011-05-31 16:54:27 +04:00
{
return single_open ( file , ab8500_gpadc_btemp_ball_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
. open = ab8500_gpadc_btemp_ball_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_main_charger_v_print ( struct seq_file * s , void * p )
{
int main_charger_v_raw ;
int main_charger_v_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
main_charger_v_raw = ab8500_gpadc_read_raw ( gpadc , MAIN_CHARGER_V ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
main_charger_v_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
MAIN_CHARGER_V , main_charger_v_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
main_charger_v_convert , main_charger_v_raw ) ;
}
static int ab8500_gpadc_main_charger_v_open ( struct inode * inode ,
2013-02-26 16:05:15 +04:00
struct file * file )
2011-05-31 16:54:27 +04:00
{
return single_open ( file , ab8500_gpadc_main_charger_v_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2011-05-31 16:54:27 +04:00
}
static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
. open = ab8500_gpadc_main_charger_v_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_acc_detect1_print ( struct seq_file * s , void * p )
{
int acc_detect1_raw ;
int acc_detect1_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
acc_detect1_raw = ab8500_gpadc_read_raw ( gpadc , ACC_DETECT1 ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
acc_detect1_convert = ab8500_gpadc_ad_to_voltage ( gpadc , ACC_DETECT1 ,
2013-02-26 14:06:55 +04:00
acc_detect1_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
acc_detect1_convert , acc_detect1_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_acc_detect1_open ( struct inode * inode ,
2013-02-26 16:05:15 +04:00
struct file * file )
2011-05-31 16:54:27 +04:00
{
return single_open ( file , ab8500_gpadc_acc_detect1_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2011-05-31 16:54:27 +04:00
}
static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
. open = ab8500_gpadc_acc_detect1_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_acc_detect2_print ( struct seq_file * s , void * p )
{
int acc_detect2_raw ;
int acc_detect2_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
acc_detect2_raw = ab8500_gpadc_read_raw ( gpadc , ACC_DETECT2 ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
acc_detect2_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
ACC_DETECT2 , acc_detect2_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
acc_detect2_convert , acc_detect2_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_acc_detect2_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8500_gpadc_acc_detect2_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2011-05-31 16:54:27 +04:00
}
static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
. open = ab8500_gpadc_acc_detect2_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_aux1_print ( struct seq_file * s , void * p )
{
int aux1_raw ;
int aux1_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
aux1_raw = ab8500_gpadc_read_raw ( gpadc , ADC_AUX1 ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
aux1_convert = ab8500_gpadc_ad_to_voltage ( gpadc , ADC_AUX1 ,
2013-02-26 14:06:55 +04:00
aux1_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
aux1_convert , aux1_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_aux1_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_aux1_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_aux1_fops = {
. open = ab8500_gpadc_aux1_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_aux2_print ( struct seq_file * s , void * p )
{
int aux2_raw ;
int aux2_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
aux2_raw = ab8500_gpadc_read_raw ( gpadc , ADC_AUX2 ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
aux2_convert = ab8500_gpadc_ad_to_voltage ( gpadc , ADC_AUX2 ,
2013-02-26 14:06:55 +04:00
aux2_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
aux2_convert , aux2_raw ) ;
}
static int ab8500_gpadc_aux2_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_aux2_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_aux2_fops = {
. open = ab8500_gpadc_aux2_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_main_bat_v_print ( struct seq_file * s , void * p )
{
int main_bat_v_raw ;
int main_bat_v_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
main_bat_v_raw = ab8500_gpadc_read_raw ( gpadc , MAIN_BAT_V ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
main_bat_v_convert = ab8500_gpadc_ad_to_voltage ( gpadc , MAIN_BAT_V ,
2013-02-26 14:06:55 +04:00
main_bat_v_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
main_bat_v_convert , main_bat_v_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_main_bat_v_open ( struct inode * inode ,
2013-02-26 16:05:15 +04:00
struct file * file )
2011-05-31 16:54:27 +04:00
{
return single_open ( file , ab8500_gpadc_main_bat_v_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
. open = ab8500_gpadc_main_bat_v_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_vbus_v_print ( struct seq_file * s , void * p )
{
int vbus_v_raw ;
int vbus_v_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
vbus_v_raw = ab8500_gpadc_read_raw ( gpadc , VBUS_V ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
vbus_v_convert = ab8500_gpadc_ad_to_voltage ( gpadc , VBUS_V ,
2013-02-26 14:06:55 +04:00
vbus_v_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
vbus_v_convert , vbus_v_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_vbus_v_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_vbus_v_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_vbus_v_fops = {
. open = ab8500_gpadc_vbus_v_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_main_charger_c_print ( struct seq_file * s , void * p )
{
int main_charger_c_raw ;
int main_charger_c_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
main_charger_c_raw = ab8500_gpadc_read_raw ( gpadc , MAIN_CHARGER_C ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
main_charger_c_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
MAIN_CHARGER_C , main_charger_c_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
main_charger_c_convert , main_charger_c_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_main_charger_c_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8500_gpadc_main_charger_c_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2011-05-31 16:54:27 +04:00
}
static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
. open = ab8500_gpadc_main_charger_c_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_usb_charger_c_print ( struct seq_file * s , void * p )
{
int usb_charger_c_raw ;
int usb_charger_c_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
usb_charger_c_raw = ab8500_gpadc_read_raw ( gpadc , USB_CHARGER_C ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
usb_charger_c_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
USB_CHARGER_C , usb_charger_c_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
usb_charger_c_convert , usb_charger_c_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_usb_charger_c_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8500_gpadc_usb_charger_c_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2011-05-31 16:54:27 +04:00
}
static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
. open = ab8500_gpadc_usb_charger_c_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_bk_bat_v_print ( struct seq_file * s , void * p )
{
int bk_bat_v_raw ;
int bk_bat_v_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
bk_bat_v_raw = ab8500_gpadc_read_raw ( gpadc , BK_BAT_V ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
bk_bat_v_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
2013-02-26 14:06:55 +04:00
BK_BAT_V , bk_bat_v_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
bk_bat_v_convert , bk_bat_v_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_bk_bat_v_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_bk_bat_v_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
. open = ab8500_gpadc_bk_bat_v_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_die_temp_print ( struct seq_file * s , void * p )
{
int die_temp_raw ;
int die_temp_convert ;
struct ab8500_gpadc * gpadc ;
2012-04-18 17:52:59 +04:00
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
2013-02-26 14:06:55 +04:00
die_temp_raw = ab8500_gpadc_read_raw ( gpadc , DIE_TEMP ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
2011-05-31 16:54:27 +04:00
die_temp_convert = ab8500_gpadc_ad_to_voltage ( gpadc , DIE_TEMP ,
2013-02-26 14:06:55 +04:00
die_temp_raw ) ;
2011-05-31 16:54:27 +04:00
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
die_temp_convert , die_temp_raw ) ;
2011-05-31 16:54:27 +04:00
}
static int ab8500_gpadc_die_temp_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_die_temp_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_die_temp_fops = {
. open = ab8500_gpadc_die_temp_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2013-02-26 18:04:37 +04:00
static int ab8500_gpadc_usb_id_print ( struct seq_file * s , void * p )
{
int usb_id_raw ;
int usb_id_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
usb_id_raw = ab8500_gpadc_read_raw ( gpadc , USB_ID ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
usb_id_convert = ab8500_gpadc_ad_to_voltage ( gpadc , USB_ID ,
usb_id_raw ) ;
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
usb_id_convert , usb_id_raw ) ;
2013-02-26 18:04:37 +04:00
}
static int ab8500_gpadc_usb_id_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_usb_id_print , inode - > i_private ) ;
}
static const struct file_operations ab8500_gpadc_usb_id_fops = {
. open = ab8500_gpadc_usb_id_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2013-02-26 18:02:31 +04:00
static int ab8540_gpadc_xtal_temp_print ( struct seq_file * s , void * p )
{
int xtal_temp_raw ;
int xtal_temp_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
xtal_temp_raw = ab8500_gpadc_read_raw ( gpadc , XTAL_TEMP ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
xtal_temp_convert = ab8500_gpadc_ad_to_voltage ( gpadc , XTAL_TEMP ,
xtal_temp_raw ) ;
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
xtal_temp_convert , xtal_temp_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_xtal_temp_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8540_gpadc_xtal_temp_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_xtal_temp_fops = {
. open = ab8540_gpadc_xtal_temp_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_vbat_true_meas_print ( struct seq_file * s , void * p )
{
int vbat_true_meas_raw ;
int vbat_true_meas_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
vbat_true_meas_raw = ab8500_gpadc_read_raw ( gpadc , VBAT_TRUE_MEAS ,
avg_sample , trig_edge , trig_timer , conv_type ) ;
vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage ( gpadc , VBAT_TRUE_MEAS ,
vbat_true_meas_raw ) ;
return seq_printf ( s , " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
vbat_true_meas_convert , vbat_true_meas_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_vbat_true_meas_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8540_gpadc_vbat_true_meas_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = {
. open = ab8540_gpadc_vbat_true_meas_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_bat_ctrl_and_ibat_print ( struct seq_file * s , void * p )
{
int bat_ctrl_raw ;
int bat_ctrl_convert ;
int ibat_raw ;
int ibat_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
bat_ctrl_raw = ab8500_gpadc_double_read_raw ( gpadc , BAT_CTRL_AND_IBAT ,
avg_sample , trig_edge , trig_timer , conv_type , & ibat_raw ) ;
bat_ctrl_convert = ab8500_gpadc_ad_to_voltage ( gpadc , BAT_CTRL ,
bat_ctrl_raw ) ;
ibat_convert = ab8500_gpadc_ad_to_voltage ( gpadc , IBAT_VIRTUAL_CHANNEL ,
ibat_raw ) ;
return seq_printf ( s , " %d,0x%X \n " " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
bat_ctrl_convert , bat_ctrl_raw ,
ibat_convert , ibat_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_bat_ctrl_and_ibat_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8540_gpadc_bat_ctrl_and_ibat_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = {
. open = ab8540_gpadc_bat_ctrl_and_ibat_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_vbat_meas_and_ibat_print ( struct seq_file * s , void * p )
{
int vbat_meas_raw ;
int vbat_meas_convert ;
int ibat_raw ;
int ibat_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
vbat_meas_raw = ab8500_gpadc_double_read_raw ( gpadc , VBAT_MEAS_AND_IBAT ,
avg_sample , trig_edge , trig_timer , conv_type , & ibat_raw ) ;
vbat_meas_convert = ab8500_gpadc_ad_to_voltage ( gpadc , MAIN_BAT_V ,
vbat_meas_raw ) ;
ibat_convert = ab8500_gpadc_ad_to_voltage ( gpadc , IBAT_VIRTUAL_CHANNEL ,
ibat_raw ) ;
return seq_printf ( s , " %d,0x%X \n " " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
vbat_meas_convert , vbat_meas_raw ,
ibat_convert , ibat_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_vbat_meas_and_ibat_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8540_gpadc_vbat_meas_and_ibat_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
. open = ab8540_gpadc_vbat_meas_and_ibat_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_vbat_true_meas_and_ibat_print ( struct seq_file * s , void * p )
{
int vbat_true_meas_raw ;
int vbat_true_meas_convert ;
int ibat_raw ;
int ibat_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
vbat_true_meas_raw = ab8500_gpadc_double_read_raw ( gpadc ,
VBAT_TRUE_MEAS_AND_IBAT , avg_sample , trig_edge ,
trig_timer , conv_type , & ibat_raw ) ;
vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage ( gpadc ,
VBAT_TRUE_MEAS , vbat_true_meas_raw ) ;
ibat_convert = ab8500_gpadc_ad_to_voltage ( gpadc , IBAT_VIRTUAL_CHANNEL ,
ibat_raw ) ;
return seq_printf ( s , " %d,0x%X \n " " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
vbat_true_meas_convert , vbat_true_meas_raw ,
ibat_convert , ibat_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_vbat_true_meas_and_ibat_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8540_gpadc_vbat_true_meas_and_ibat_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
. open = ab8540_gpadc_vbat_true_meas_and_ibat_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_bat_temp_and_ibat_print ( struct seq_file * s , void * p )
{
int bat_temp_raw ;
int bat_temp_convert ;
int ibat_raw ;
int ibat_convert ;
struct ab8500_gpadc * gpadc ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
bat_temp_raw = ab8500_gpadc_double_read_raw ( gpadc , BAT_TEMP_AND_IBAT ,
avg_sample , trig_edge , trig_timer , conv_type , & ibat_raw ) ;
bat_temp_convert = ab8500_gpadc_ad_to_voltage ( gpadc , BTEMP_BALL ,
bat_temp_raw ) ;
ibat_convert = ab8500_gpadc_ad_to_voltage ( gpadc , IBAT_VIRTUAL_CHANNEL ,
ibat_raw ) ;
return seq_printf ( s , " %d,0x%X \n " " %d,0x%X \n " ,
2013-02-26 16:05:15 +04:00
bat_temp_convert , bat_temp_raw ,
ibat_convert , ibat_raw ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_bat_temp_and_ibat_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8540_gpadc_bat_temp_and_ibat_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 18:02:31 +04:00
}
static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = {
. open = ab8540_gpadc_bat_temp_and_ibat_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8540_gpadc_otp_cal_print ( struct seq_file * s , void * p )
{
struct ab8500_gpadc * gpadc ;
u16 vmain_l , vmain_h , btemp_l , btemp_h ;
u16 vbat_l , vbat_h , ibat_l , ibat_h ;
gpadc = ab8500_gpadc_get ( " ab8500-gpadc.0 " ) ;
ab8540_gpadc_get_otp ( gpadc , & vmain_l , & vmain_h , & btemp_l , & btemp_h ,
& vbat_l , & vbat_h , & ibat_l , & ibat_h ) ;
return seq_printf ( s , " VMAIN_L:0x%X \n "
2013-02-26 16:05:15 +04:00
" VMAIN_H:0x%X \n "
" BTEMP_L:0x%X \n "
" BTEMP_H:0x%X \n "
" VBAT_L:0x%X \n "
" VBAT_H:0x%X \n "
" IBAT_L:0x%X \n "
" IBAT_H:0x%X \n " ,
vmain_l , vmain_h , btemp_l , btemp_h , vbat_l , vbat_h , ibat_l , ibat_h ) ;
2013-02-26 18:02:31 +04:00
}
static int ab8540_gpadc_otp_cal_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8540_gpadc_otp_cal_print , inode - > i_private ) ;
}
static const struct file_operations ab8540_gpadc_otp_calib_fops = {
. open = ab8540_gpadc_otp_cal_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2013-02-26 14:06:55 +04:00
static int ab8500_gpadc_avg_sample_print ( struct seq_file * s , void * p )
{
return seq_printf ( s , " %d \n " , avg_sample ) ;
}
static int ab8500_gpadc_avg_sample_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_avg_sample_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 14:06:55 +04:00
}
static ssize_t ab8500_gpadc_avg_sample_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_avg_sample ;
int err ;
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_avg_sample ) ;
2013-02-26 14:06:55 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-02-26 14:06:55 +04:00
if ( ( user_avg_sample = = SAMPLE_1 ) | | ( user_avg_sample = = SAMPLE_4 )
| | ( user_avg_sample = = SAMPLE_8 )
| | ( user_avg_sample = = SAMPLE_16 ) ) {
avg_sample = ( u8 ) user_avg_sample ;
} else {
dev_err ( dev , " debugfs error input: "
" should be egal to 1, 4, 8 or 16 \n " ) ;
return - EINVAL ;
}
2012-11-23 13:41:00 +04:00
return count ;
2013-02-26 14:06:55 +04:00
}
static const struct file_operations ab8500_gpadc_avg_sample_fops = {
. open = ab8500_gpadc_avg_sample_open ,
. read = seq_read ,
. write = ab8500_gpadc_avg_sample_write ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_trig_edge_print ( struct seq_file * s , void * p )
{
return seq_printf ( s , " %d \n " , trig_edge ) ;
}
static int ab8500_gpadc_trig_edge_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_trig_edge_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 14:06:55 +04:00
}
static ssize_t ab8500_gpadc_trig_edge_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_trig_edge ;
int err ;
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_trig_edge ) ;
2013-02-26 14:06:55 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-02-26 14:06:55 +04:00
if ( ( user_trig_edge = = RISING_EDGE )
| | ( user_trig_edge = = FALLING_EDGE ) ) {
trig_edge = ( u8 ) user_trig_edge ;
} else {
dev_err ( dev , " Wrong input: \n "
" Enter 0. Rising edge \n "
" Enter 1. Falling edge \n " ) ;
return - EINVAL ;
}
2012-11-23 13:41:00 +04:00
return count ;
2013-02-26 14:06:55 +04:00
}
static const struct file_operations ab8500_gpadc_trig_edge_fops = {
. open = ab8500_gpadc_trig_edge_open ,
. read = seq_read ,
. write = ab8500_gpadc_trig_edge_write ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_trig_timer_print ( struct seq_file * s , void * p )
{
return seq_printf ( s , " %d \n " , trig_timer ) ;
}
static int ab8500_gpadc_trig_timer_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_trig_timer_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 14:06:55 +04:00
}
static ssize_t ab8500_gpadc_trig_timer_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_trig_timer ;
int err ;
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_trig_timer ) ;
2013-02-26 14:06:55 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-02-26 14:06:55 +04:00
if ( ( user_trig_timer > = 0 ) & & ( user_trig_timer < = 255 ) ) {
trig_timer = ( u8 ) user_trig_timer ;
} else {
dev_err ( dev , " debugfs error input: "
" should be beetween 0 to 255 \n " ) ;
return - EINVAL ;
}
2012-11-23 13:41:00 +04:00
return count ;
2013-02-26 14:06:55 +04:00
}
static const struct file_operations ab8500_gpadc_trig_timer_fops = {
. open = ab8500_gpadc_trig_timer_open ,
. read = seq_read ,
. write = ab8500_gpadc_trig_timer_write ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static int ab8500_gpadc_conv_type_print ( struct seq_file * s , void * p )
{
return seq_printf ( s , " %d \n " , conv_type ) ;
}
static int ab8500_gpadc_conv_type_open ( struct inode * inode , struct file * file )
{
return single_open ( file , ab8500_gpadc_conv_type_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-02-26 14:06:55 +04:00
}
static ssize_t ab8500_gpadc_conv_type_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_conv_type ;
int err ;
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_conv_type ) ;
2013-02-26 14:06:55 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-02-26 14:06:55 +04:00
if ( ( user_conv_type = = ADC_SW )
| | ( user_conv_type = = ADC_HW ) ) {
conv_type = ( u8 ) user_conv_type ;
} else {
dev_err ( dev , " Wrong input: \n "
" Enter 0. ADC SW conversion \n "
" Enter 1. ADC HW conversion \n " ) ;
return - EINVAL ;
}
2012-11-23 13:41:00 +04:00
return count ;
2013-02-26 14:06:55 +04:00
}
static const struct file_operations ab8500_gpadc_conv_type_fops = {
. open = ab8500_gpadc_conv_type_open ,
. read = seq_read ,
. write = ab8500_gpadc_conv_type_write ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2011-04-08 18:26:36 +04:00
/*
* return length of an ASCII numerical value , 0 is string is not a
* numerical value .
* string shall start at value 1 st char .
* string can be tailed with \ 0 or space or newline chars only .
* value can be decimal or hexadecimal ( prefixed 0 x or 0 X ) .
*/
static int strval_len ( char * b )
{
char * s = b ;
if ( ( * s = = ' 0 ' ) & & ( ( * ( s + 1 ) = = ' x ' ) | | ( * ( s + 1 ) = = ' X ' ) ) ) {
s + = 2 ;
for ( ; * s & & ( * s ! = ' ' ) & & ( * s ! = ' \n ' ) ; s + + ) {
if ( ! isxdigit ( * s ) )
return 0 ;
}
} else {
if ( * s = = ' - ' )
s + + ;
for ( ; * s & & ( * s ! = ' ' ) & & ( * s ! = ' \n ' ) ; s + + ) {
if ( ! isdigit ( * s ) )
return 0 ;
}
}
return ( int ) ( s - b ) ;
}
/*
* parse hwreg input data .
* update global hwreg_cfg only if input data syntax is ok .
*/
static ssize_t hwreg_common_write ( char * b , struct hwreg_cfg * cfg ,
struct device * dev )
{
uint write , val = 0 ;
u8 regvalue ;
int ret ;
struct hwreg_cfg loc = {
. bank = 0 , /* default: invalid phys addr */
. addr = 0 , /* default: invalid phys addr */
. fmt = 0 , /* default: 32bit access, hex output */
. mask = 0xFFFFFFFF , /* default: no mask */
. shift = 0 , /* default: no bit shift */
} ;
/* read or write ? */
if ( ! strncmp ( b , " read " , 5 ) ) {
write = 0 ;
b + = 5 ;
} else if ( ! strncmp ( b , " write " , 6 ) ) {
write = 1 ;
b + = 6 ;
} else
return - EINVAL ;
/* OPTIONS -l|-w|-b -s -m -o */
while ( ( * b = = ' ' ) | | ( * b = = ' - ' ) ) {
if ( * ( b - 1 ) ! = ' ' ) {
b + + ;
continue ;
}
if ( ( ! strncmp ( b , " -d " , 3 ) ) | |
( ! strncmp ( b , " -dec " , 5 ) ) ) {
b + = ( * ( b + 2 ) = = ' ' ) ? 3 : 5 ;
loc . fmt | = ( 1 < < 0 ) ;
} else if ( ( ! strncmp ( b , " -h " , 3 ) ) | |
( ! strncmp ( b , " -hex " , 5 ) ) ) {
b + = ( * ( b + 2 ) = = ' ' ) ? 3 : 5 ;
loc . fmt & = ~ ( 1 < < 0 ) ;
} else if ( ( ! strncmp ( b , " -m " , 3 ) ) | |
( ! strncmp ( b , " -mask " , 6 ) ) ) {
b + = ( * ( b + 2 ) = = ' ' ) ? 3 : 6 ;
if ( strval_len ( b ) = = 0 )
return - EINVAL ;
loc . mask = simple_strtoul ( b , & b , 0 ) ;
} else if ( ( ! strncmp ( b , " -s " , 3 ) ) | |
( ! strncmp ( b , " -shift " , 7 ) ) ) {
b + = ( * ( b + 2 ) = = ' ' ) ? 3 : 7 ;
if ( strval_len ( b ) = = 0 )
return - EINVAL ;
loc . shift = simple_strtol ( b , & b , 0 ) ;
} else {
return - EINVAL ;
}
}
/* get arg BANK and ADDRESS */
if ( strval_len ( b ) = = 0 )
return - EINVAL ;
loc . bank = simple_strtoul ( b , & b , 0 ) ;
while ( * b = = ' ' )
b + + ;
if ( strval_len ( b ) = = 0 )
return - EINVAL ;
loc . addr = simple_strtoul ( b , & b , 0 ) ;
if ( write ) {
while ( * b = = ' ' )
b + + ;
if ( strval_len ( b ) = = 0 )
return - EINVAL ;
val = simple_strtoul ( b , & b , 0 ) ;
}
/* args are ok, update target cfg (mainly for read) */
* cfg = loc ;
# ifdef ABB_HWREG_DEBUG
pr_warn ( " HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d "
" value=0x%X \n " , ( write ) ? " write " : " read " ,
REG_FMT_DEC ( cfg ) ? " decimal " : " hexa " ,
cfg - > addr , cfg - > mask , cfg - > shift , val ) ;
# endif
if ( ! write )
return 0 ;
ret = abx500_get_register_interruptible ( dev ,
( u8 ) cfg - > bank , ( u8 ) cfg - > addr , & regvalue ) ;
if ( ret < 0 ) {
dev_err ( dev , " abx500_get_reg fail %d, %d \n " ,
ret , __LINE__ ) ;
return - EINVAL ;
}
if ( cfg - > shift > = 0 ) {
regvalue & = ~ ( cfg - > mask < < ( cfg - > shift ) ) ;
val = ( val & cfg - > mask ) < < ( cfg - > shift ) ;
} else {
regvalue & = ~ ( cfg - > mask > > ( - cfg - > shift ) ) ;
val = ( val & cfg - > mask ) > > ( - cfg - > shift ) ;
}
val = val | regvalue ;
ret = abx500_set_register_interruptible ( dev ,
( u8 ) cfg - > bank , ( u8 ) cfg - > addr , ( u8 ) val ) ;
if ( ret < 0 ) {
pr_err ( " abx500_set_reg failed %d, %d " , ret , __LINE__ ) ;
return - EINVAL ;
}
return 0 ;
}
static ssize_t ab8500_hwreg_write ( struct file * file ,
const char __user * user_buf , size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
char buf [ 128 ] ;
int buf_size , ret ;
/* Get userspace string and assure termination */
buf_size = min ( count , ( sizeof ( buf ) - 1 ) ) ;
if ( copy_from_user ( buf , user_buf , buf_size ) )
return - EFAULT ;
buf [ buf_size ] = 0 ;
/* get args and process */
ret = hwreg_common_write ( buf , & hwreg_cfg , dev ) ;
return ( ret ) ? ret : buf_size ;
}
/*
* - irq subscribe / unsubscribe stuff
*/
2013-01-14 20:10:36 +04:00
static int ab8500_subscribe_unsubscribe_print ( struct seq_file * s , void * p )
{
seq_printf ( s , " %d \n " , irq_first ) ;
return 0 ;
}
static int ab8500_subscribe_unsubscribe_open ( struct inode * inode ,
struct file * file )
{
return single_open ( file , ab8500_subscribe_unsubscribe_print ,
2013-02-26 16:05:15 +04:00
inode - > i_private ) ;
2013-01-14 20:10:36 +04:00
}
/*
2010-11-19 19:55:11 +03:00
* Userspace should use poll ( ) on this file . When an event occur
2013-01-14 20:10:36 +04:00
* the blocking poll will be released .
*/
static ssize_t show_irq ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
2010-11-19 19:55:11 +03:00
unsigned long name ;
unsigned int irq_index ;
int err ;
2013-01-14 20:10:36 +04:00
2013-06-04 08:11:50 +04:00
err = kstrtoul ( attr - > attr . name , 0 , & name ) ;
2010-11-19 19:55:11 +03:00
if ( err )
return err ;
irq_index = name - irq_first ;
2012-02-03 14:19:05 +04:00
if ( irq_index > = num_irqs )
2010-11-19 19:55:11 +03:00
return - EINVAL ;
else
return sprintf ( buf , " %u \n " , irq_count [ irq_index ] ) ;
}
2013-01-14 20:10:36 +04:00
static ssize_t ab8500_subscribe_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_val ;
int err ;
2010-11-19 19:55:11 +03:00
unsigned int irq_index ;
2013-01-14 20:10:36 +04:00
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_val ) ;
2013-01-14 20:10:36 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-01-14 20:10:36 +04:00
if ( user_val < irq_first ) {
dev_err ( dev , " debugfs error input < %d \n " , irq_first ) ;
return - EINVAL ;
}
if ( user_val > irq_last ) {
dev_err ( dev , " debugfs error input > %d \n " , irq_last ) ;
return - EINVAL ;
}
2010-11-19 19:55:11 +03:00
irq_index = user_val - irq_first ;
2012-02-03 14:19:05 +04:00
if ( irq_index > = num_irqs )
2010-11-19 19:55:11 +03:00
return - EINVAL ;
2013-01-14 20:10:36 +04:00
/*
2010-11-19 19:55:11 +03:00
* This will create a sysfs file named < irq - nr > which userspace can
2013-01-14 20:10:36 +04:00
* use to select or poll and get the AB8500 events
*/
2010-11-19 19:55:11 +03:00
dev_attr [ irq_index ] = kmalloc ( sizeof ( struct device_attribute ) ,
GFP_KERNEL ) ;
2013-07-19 11:44:50 +04:00
if ( ! dev_attr [ irq_index ] )
return - ENOMEM ;
2012-11-23 13:41:00 +04:00
event_name [ irq_index ] = kmalloc ( count , GFP_KERNEL ) ;
2013-07-19 11:53:24 +04:00
if ( ! event_name [ irq_index ] )
return - ENOMEM ;
2010-11-19 19:55:11 +03:00
sprintf ( event_name [ irq_index ] , " %lu " , user_val ) ;
dev_attr [ irq_index ] - > show = show_irq ;
dev_attr [ irq_index ] - > store = NULL ;
dev_attr [ irq_index ] - > attr . name = event_name [ irq_index ] ;
dev_attr [ irq_index ] - > attr . mode = S_IRUGO ;
err = sysfs_create_file ( & dev - > kobj , & dev_attr [ irq_index ] - > attr ) ;
2013-01-14 20:10:36 +04:00
if ( err < 0 ) {
printk ( KERN_ERR " sysfs_create_file failed %d \n " , err ) ;
return err ;
}
err = request_threaded_irq ( user_val , NULL , ab8500_debug_handler ,
IRQF_SHARED | IRQF_NO_SUSPEND ,
" ab8500-debug " , & dev - > kobj ) ;
if ( err < 0 ) {
printk ( KERN_ERR " request_threaded_irq failed %d, %lu \n " ,
err , user_val ) ;
2010-11-19 19:55:11 +03:00
sysfs_remove_file ( & dev - > kobj , & dev_attr [ irq_index ] - > attr ) ;
2013-01-14 20:10:36 +04:00
return err ;
}
2012-11-23 13:41:00 +04:00
return count ;
2013-01-14 20:10:36 +04:00
}
static ssize_t ab8500_unsubscribe_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct device * dev = ( ( struct seq_file * ) ( file - > private_data ) ) - > private ;
unsigned long user_val ;
int err ;
2010-11-19 19:55:11 +03:00
unsigned int irq_index ;
2013-01-14 20:10:36 +04:00
2012-11-23 13:41:00 +04:00
err = kstrtoul_from_user ( user_buf , count , 0 , & user_val ) ;
2013-01-14 20:10:36 +04:00
if ( err )
2012-11-23 13:41:00 +04:00
return err ;
2013-01-14 20:10:36 +04:00
if ( user_val < irq_first ) {
dev_err ( dev , " debugfs error input < %d \n " , irq_first ) ;
return - EINVAL ;
}
if ( user_val > irq_last ) {
dev_err ( dev , " debugfs error input > %d \n " , irq_last ) ;
return - EINVAL ;
}
2010-11-19 19:55:11 +03:00
irq_index = user_val - irq_first ;
2012-02-03 14:19:05 +04:00
if ( irq_index > = num_irqs )
2010-11-19 19:55:11 +03:00
return - EINVAL ;
/* Set irq count to 0 when unsubscribe */
irq_count [ irq_index ] = 0 ;
if ( dev_attr [ irq_index ] )
sysfs_remove_file ( & dev - > kobj , & dev_attr [ irq_index ] - > attr ) ;
2013-01-14 20:10:36 +04:00
2010-11-19 19:55:11 +03:00
free_irq ( user_val , & dev - > kobj ) ;
kfree ( event_name [ irq_index ] ) ;
kfree ( dev_attr [ irq_index ] ) ;
2013-01-14 20:10:36 +04:00
2012-11-23 13:41:00 +04:00
return count ;
2013-01-14 20:10:36 +04:00
}
2011-04-08 18:26:36 +04:00
/*
* - several deubgfs nodes fops
*/
2010-09-13 18:05:04 +04:00
static const struct file_operations ab8500_bank_fops = {
2010-11-26 15:06:39 +03:00
. open = ab8500_bank_open ,
. write = ab8500_bank_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
2010-09-13 18:05:04 +04:00
} ;
static const struct file_operations ab8500_address_fops = {
2010-11-26 15:06:39 +03:00
. open = ab8500_address_open ,
. write = ab8500_address_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
2010-09-13 18:05:04 +04:00
} ;
static const struct file_operations ab8500_val_fops = {
2010-11-26 15:06:39 +03:00
. open = ab8500_val_open ,
. write = ab8500_val_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
2010-09-13 18:05:04 +04:00
} ;
2012-02-14 16:01:00 +04:00
static const struct file_operations ab8500_interrupts_fops = {
. open = ab8500_interrupts_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2013-01-14 20:10:36 +04:00
static const struct file_operations ab8500_subscribe_fops = {
. open = ab8500_subscribe_unsubscribe_open ,
. write = ab8500_subscribe_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static const struct file_operations ab8500_unsubscribe_fops = {
. open = ab8500_subscribe_unsubscribe_open ,
. write = ab8500_unsubscribe_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2011-04-08 18:26:36 +04:00
static const struct file_operations ab8500_hwreg_fops = {
. open = ab8500_hwreg_open ,
. write = ab8500_hwreg_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
2010-09-13 18:05:04 +04:00
static struct dentry * ab8500_dir ;
2011-05-31 16:54:27 +04:00
static struct dentry * ab8500_gpadc_dir ;
2010-09-13 18:05:04 +04:00
2012-11-19 22:23:04 +04:00
static int ab8500_debug_probe ( struct platform_device * plf )
2010-09-13 18:05:04 +04:00
{
2011-04-08 18:26:36 +04:00
struct dentry * file ;
2012-02-03 14:19:05 +04:00
struct ab8500 * ab8500 ;
2013-04-12 19:02:09 +04:00
struct resource * res ;
2010-11-26 15:06:39 +03:00
debug_bank = AB8500_MISC ;
debug_address = AB8500_REV_REG & 0x00FF ;
2010-09-13 18:05:04 +04:00
2012-02-03 14:19:05 +04:00
ab8500 = dev_get_drvdata ( plf - > dev . parent ) ;
num_irqs = ab8500 - > mask_size ;
2013-05-23 19:25:05 +04:00
irq_count = devm_kzalloc ( & plf - > dev ,
sizeof ( * irq_count ) * num_irqs , GFP_KERNEL ) ;
2012-02-03 14:19:05 +04:00
if ( ! irq_count )
return - ENOMEM ;
2013-05-23 19:25:05 +04:00
dev_attr = devm_kzalloc ( & plf - > dev ,
sizeof ( * dev_attr ) * num_irqs , GFP_KERNEL ) ;
2012-02-03 14:19:05 +04:00
if ( ! dev_attr )
2013-05-23 19:25:05 +04:00
return - ENOMEM ;
2012-02-03 14:19:05 +04:00
2013-05-23 19:25:05 +04:00
event_name = devm_kzalloc ( & plf - > dev ,
sizeof ( * event_name ) * num_irqs , GFP_KERNEL ) ;
2012-02-03 14:19:05 +04:00
if ( ! event_name )
2013-05-23 19:25:05 +04:00
return - ENOMEM ;
2012-02-03 14:19:05 +04:00
2013-04-12 19:02:09 +04:00
res = platform_get_resource_byname ( plf , 0 , " IRQ_AB8500 " ) ;
if ( ! res ) {
dev_err ( & plf - > dev , " AB8500 irq not found, err %d \n " ,
irq_first ) ;
2013-05-23 19:25:05 +04:00
return ENXIO ;
2013-04-12 19:02:09 +04:00
}
irq_ab8500 = res - > start ;
2013-01-14 20:10:36 +04:00
irq_first = platform_get_irq_byname ( plf , " IRQ_FIRST " ) ;
if ( irq_first < 0 ) {
dev_err ( & plf - > dev , " First irq not found, err %d \n " ,
2013-02-26 16:05:15 +04:00
irq_first ) ;
2013-05-23 19:25:05 +04:00
return irq_first ;
2013-01-14 20:10:36 +04:00
}
irq_last = platform_get_irq_byname ( plf , " IRQ_LAST " ) ;
if ( irq_last < 0 ) {
dev_err ( & plf - > dev , " Last irq not found, err %d \n " ,
2013-02-26 16:05:15 +04:00
irq_last ) ;
2013-05-23 19:25:05 +04:00
return irq_last ;
2013-01-14 20:10:36 +04:00
}
2010-11-26 15:06:39 +03:00
ab8500_dir = debugfs_create_dir ( AB8500_NAME_STRING , NULL ) ;
if ( ! ab8500_dir )
2011-04-08 18:26:36 +04:00
goto err ;
2010-09-13 18:05:04 +04:00
2011-05-31 16:54:27 +04:00
ab8500_gpadc_dir = debugfs_create_dir ( AB8500_ADC_NAME_STRING ,
2013-02-26 16:05:15 +04:00
ab8500_dir ) ;
2011-05-31 16:54:27 +04:00
if ( ! ab8500_gpadc_dir )
goto err ;
file = debugfs_create_file ( " all-bank-registers " , S_IRUGO ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_registers_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2012-01-26 18:39:20 +04:00
file = debugfs_create_file ( " all-banks " , S_IRUGO ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_all_banks_fops ) ;
2012-01-26 18:39:20 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " register-bank " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_bank_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " register-address " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_address_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " register-value " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_val_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " irq-subscribe " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_subscribe_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2012-07-06 18:11:50 +04:00
if ( is_ab8500 ( ab8500 ) ) {
debug_ranges = ab8500_debug_ranges ;
2012-02-14 16:01:00 +04:00
num_interrupt_lines = AB8500_NR_IRQS ;
2012-07-06 18:11:50 +04:00
} else if ( is_ab8505 ( ab8500 ) ) {
debug_ranges = ab8505_debug_ranges ;
2012-02-14 16:01:00 +04:00
num_interrupt_lines = AB8505_NR_IRQS ;
2012-07-06 18:11:50 +04:00
} else if ( is_ab9540 ( ab8500 ) ) {
debug_ranges = ab8505_debug_ranges ;
2012-02-14 16:01:00 +04:00
num_interrupt_lines = AB9540_NR_IRQS ;
2012-07-06 18:11:50 +04:00
} else if ( is_ab8540 ( ab8500 ) ) {
2012-11-19 15:20:03 +04:00
debug_ranges = ab8540_debug_ranges ;
2013-02-26 14:09:41 +04:00
num_interrupt_lines = AB8540_NR_IRQS ;
2012-07-06 18:11:50 +04:00
}
2012-02-14 16:01:00 +04:00
file = debugfs_create_file ( " interrupts " , ( S_IRUGO ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_interrupts_fops ) ;
2012-02-14 16:01:00 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " irq-unsubscribe " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_unsubscribe_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " hwreg " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_dir , & plf - > dev , & ab8500_hwreg_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " all-modem-registers " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 18:03:33 +04:00
ab8500_dir , & plf - > dev , & ab8500_modem_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " bat_ctrl " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_bat_ctrl_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " btemp_ball " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_btemp_ball_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " main_charger_v " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_main_charger_v_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " acc_detect1 " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_acc_detect1_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " acc_detect2 " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_acc_detect2_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " adc_aux1 " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_aux1_fops ) ;
2011-05-31 16:54:27 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " adc_aux2 " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_aux2_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2010-09-13 18:05:04 +04:00
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " main_bat_v " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_main_bat_v_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2010-09-13 18:05:04 +04:00
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " vbus_v " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_vbus_v_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2010-09-13 18:05:04 +04:00
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " main_charger_c " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_main_charger_c_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " usb_charger_c " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_usb_charger_c_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " bk_bat_v " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_bk_bat_v_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " die_temp " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 16:05:15 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_die_temp_fops ) ;
2011-04-08 18:26:36 +04:00
if ( ! file )
goto err ;
2013-02-26 18:04:37 +04:00
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " usb_id " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 18:04:37 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_usb_id_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:02:31 +04:00
if ( is_ab8540 ( ab8500 ) ) {
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " xtal_temp " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 18:02:31 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8540_gpadc_xtal_temp_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " vbattruemeas " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 18:02:31 +04:00
ab8500_gpadc_dir , & plf - > dev ,
& ab8540_gpadc_vbat_true_meas_fops ) ;
if ( ! file )
goto err ;
file = debugfs_create_file ( " batctrl_and_ibat " ,
2013-02-26 16:05:15 +04:00
( S_IRUGO | S_IWUGO ) , ab8500_gpadc_dir ,
& plf - > dev , & ab8540_gpadc_bat_ctrl_and_ibat_fops ) ;
2013-02-26 18:02:31 +04:00
if ( ! file )
goto err ;
file = debugfs_create_file ( " vbatmeas_and_ibat " ,
2013-02-26 16:05:15 +04:00
( S_IRUGO | S_IWUGO ) , ab8500_gpadc_dir ,
& plf - > dev ,
& ab8540_gpadc_vbat_meas_and_ibat_fops ) ;
2013-02-26 18:02:31 +04:00
if ( ! file )
goto err ;
file = debugfs_create_file ( " vbattruemeas_and_ibat " ,
2013-02-26 16:05:15 +04:00
( S_IRUGO | S_IWUGO ) , ab8500_gpadc_dir ,
& plf - > dev ,
& ab8540_gpadc_vbat_true_meas_and_ibat_fops ) ;
2013-02-26 18:02:31 +04:00
if ( ! file )
goto err ;
file = debugfs_create_file ( " battemp_and_ibat " ,
2013-02-26 16:05:15 +04:00
( S_IRUGO | S_IWUGO ) , ab8500_gpadc_dir ,
& plf - > dev , & ab8540_gpadc_bat_temp_and_ibat_fops ) ;
2013-02-26 18:02:31 +04:00
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " otp_calib " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 18:02:31 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8540_gpadc_otp_calib_fops ) ;
if ( ! file )
goto err ;
}
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " avg_sample " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 14:06:55 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_avg_sample_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " trig_edge " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 14:06:55 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_trig_edge_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " trig_timer " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 14:06:55 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_trig_timer_fops ) ;
if ( ! file )
goto err ;
2013-02-26 18:09:08 +04:00
file = debugfs_create_file ( " conv_type " , ( S_IRUGO | S_IWUSR | S_IWGRP ) ,
2013-02-26 14:06:55 +04:00
ab8500_gpadc_dir , & plf - > dev , & ab8500_gpadc_conv_type_fops ) ;
if ( ! file )
goto err ;
2013-01-14 20:10:36 +04:00
2010-11-26 15:06:39 +03:00
return 0 ;
2010-09-13 18:05:04 +04:00
2011-04-08 18:26:36 +04:00
err :
if ( ab8500_dir )
debugfs_remove_recursive ( ab8500_dir ) ;
2010-11-26 15:06:39 +03:00
dev_err ( & plf - > dev , " failed to create debugfs entries. \n " ) ;
2012-02-03 14:19:05 +04:00
2013-05-23 19:25:05 +04:00
return - ENOMEM ;
2010-09-13 18:05:04 +04:00
}
2012-11-19 22:26:01 +04:00
static int ab8500_debug_remove ( struct platform_device * plf )
2010-09-13 18:05:04 +04:00
{
2011-04-08 18:26:36 +04:00
debugfs_remove_recursive ( ab8500_dir ) ;
2012-02-03 14:19:05 +04:00
2010-11-26 15:06:39 +03:00
return 0 ;
2010-09-13 18:05:04 +04:00
}
static struct platform_driver ab8500_debug_driver = {
2010-11-26 15:06:39 +03:00
. driver = {
. name = " ab8500-debug " ,
. owner = THIS_MODULE ,
} ,
. probe = ab8500_debug_probe ,
2012-11-19 22:20:24 +04:00
. remove = ab8500_debug_remove
2010-09-13 18:05:04 +04:00
} ;
static int __init ab8500_debug_init ( void )
{
2010-11-26 15:06:39 +03:00
return platform_driver_register ( & ab8500_debug_driver ) ;
2010-09-13 18:05:04 +04:00
}
static void __exit ab8500_debug_exit ( void )
{
2010-11-26 15:06:39 +03:00
platform_driver_unregister ( & ab8500_debug_driver ) ;
2010-09-13 18:05:04 +04:00
}
subsys_initcall ( ab8500_debug_init ) ;
module_exit ( ab8500_debug_exit ) ;
MODULE_AUTHOR ( " Mattias WALLIN <mattias.wallin@stericsson.com " ) ;
MODULE_DESCRIPTION ( " AB8500 DEBUG " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;