Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
62696579
Commit
62696579
authored
Sep 01, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'regulator/topic/da9063' into regulator-next
parents
1ad13028
632b3d62
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1440 additions
and
0 deletions
+1440
-0
drivers/regulator/Kconfig
drivers/regulator/Kconfig
+20
-0
drivers/regulator/Makefile
drivers/regulator/Makefile
+2
-0
drivers/regulator/da9063-regulator.c
drivers/regulator/da9063-regulator.c
+934
-0
drivers/regulator/da9210-regulator.c
drivers/regulator/da9210-regulator.c
+196
-0
drivers/regulator/da9210-regulator.h
drivers/regulator/da9210-regulator.h
+288
-0
No files found.
drivers/regulator/Kconfig
View file @
62696579
...
@@ -157,6 +157,26 @@ config REGULATOR_DA9055
...
@@ -157,6 +157,26 @@ config REGULATOR_DA9055
This driver can also be built as a module. If so, the module
This driver can also be built as a module. If so, the module
will be called da9055-regulator.
will be called da9055-regulator.
config REGULATOR_DA9063
tristate "Dialog Semiconductor DA9063 regulators"
depends on MFD_DA9063
help
Say y here to support the BUCKs and LDOs regulators found on
DA9063 PMICs.
This driver can also be built as a module. If so, the module
will be called da9063-regulator.
config REGULATOR_DA9210
tristate "Dialog Semiconductor DA9210 regulator"
depends on I2C
select REGMAP_I2C
help
Say y here to support for the Dialog Semiconductor DA9210.
The DA9210 is a multi-phase synchronous step down
converter 12A DC-DC Buck controlled through an I2C
interface.
config REGULATOR_DBX500_PRCMU
config REGULATOR_DBX500_PRCMU
bool
bool
...
...
drivers/regulator/Makefile
View file @
62696579
...
@@ -21,6 +21,8 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
...
@@ -21,6 +21,8 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_DA903X)
+=
da903x.o
obj-$(CONFIG_REGULATOR_DA903X)
+=
da903x.o
obj-$(CONFIG_REGULATOR_DA9052)
+=
da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9052)
+=
da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055)
+=
da9055-regulator.o
obj-$(CONFIG_REGULATOR_DA9055)
+=
da9055-regulator.o
obj-$(CONFIG_REGULATOR_DA9063)
+=
da9063-regulator.o
obj-$(CONFIG_REGULATOR_DA9210)
+=
da9210-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU)
+=
dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU)
+=
dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU)
+=
db8500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU)
+=
db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555)
+=
fan53555.o
obj-$(CONFIG_REGULATOR_FAN53555)
+=
fan53555.o
...
...
drivers/regulator/da9063-regulator.c
0 → 100644
View file @
62696579
/*
* Regulator driver for DA9063 PMIC series
*
* Copyright 2012 Dialog Semiconductors Ltd.
* Copyright 2013 Philipp Zabel, Pengutronix
*
* Author: Krystian Garbaciak <krystian.garbaciak@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/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
/* Definition for registering regmap bit fields using a mask */
#define BFIELD(_reg, _mask) \
REG_FIELD(_reg, __builtin_ffs((int)_mask) - 1, \
sizeof(unsigned int) * 8 - __builtin_clz((_mask)) - 1)
/* Regulator capabilities and registers description */
struct
da9063_regulator_info
{
struct
regulator_desc
desc
;
/* Current limiting */
unsigned
n_current_limits
;
const
int
*
current_limits
;
/* DA9063 main register fields */
struct
reg_field
mode
;
/* buck mode of operation */
struct
reg_field
suspend
;
struct
reg_field
sleep
;
struct
reg_field
suspend_sleep
;
unsigned
int
suspend_vsel_reg
;
struct
reg_field
ilimit
;
/* DA9063 event detection bit */
struct
reg_field
oc_event
;
};
/* Macros for LDO */
#define DA9063_LDO(chip, regl_name, min_mV, step_mV, max_mV) \
.desc.id = chip##_ID_##regl_name, \
.desc.name = __stringify(chip##_##regl_name), \
.desc.ops = &da9063_ldo_ops, \
.desc.min_uV = (min_mV) * 1000, \
.desc.uV_step = (step_mV) * 1000, \
.desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \
.desc.enable_reg = DA9063_REG_##regl_name##_CONT, \
.desc.enable_mask = DA9063_LDO_EN, \
.desc.vsel_reg = DA9063_REG_V##regl_name##_A, \
.desc.vsel_mask = DA9063_V##regl_name##_MASK, \
.desc.linear_min_sel = DA9063_V##regl_name##_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_LDO_SL), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_LDO_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B
/* Macros for voltage DC/DC converters (BUCKs) */
#define DA9063_BUCK(chip, regl_name, min_mV, step_mV, max_mV, limits_array) \
.desc.id = chip##_ID_##regl_name, \
.desc.name = __stringify(chip##_##regl_name), \
.desc.ops = &da9063_buck_ops, \
.desc.min_uV = (min_mV) * 1000, \
.desc.uV_step = (step_mV) * 1000, \
.desc.n_voltages = ((max_mV) - (min_mV))/(step_mV) + 1, \
.current_limits = limits_array, \
.n_current_limits = ARRAY_SIZE(limits_array)
#define DA9063_BUCK_COMMON_FIELDS(regl_name) \
.desc.enable_reg = DA9063_REG_##regl_name##_CONT, \
.desc.enable_mask = DA9063_BUCK_EN, \
.desc.vsel_reg = DA9063_REG_V##regl_name##_A, \
.desc.vsel_mask = DA9063_VBUCK_MASK, \
.desc.linear_min_sel = DA9063_VBUCK_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_BUCK_SL), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_BUCK_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B, \
.mode = BFIELD(DA9063_REG_##regl_name##_CFG, DA9063_BUCK_MODE_MASK)
/* Defines asignment of regulators info table to chip model */
struct
da9063_dev_model
{
const
struct
da9063_regulator_info
*
regulator_info
;
unsigned
n_regulators
;
unsigned
dev_model
;
};
/* Single regulator settings */
struct
da9063_regulator
{
struct
regulator_desc
desc
;
struct
regulator_dev
*
rdev
;
struct
da9063
*
hw
;
const
struct
da9063_regulator_info
*
info
;
struct
regmap_field
*
mode
;
struct
regmap_field
*
suspend
;
struct
regmap_field
*
sleep
;
struct
regmap_field
*
suspend_sleep
;
struct
regmap_field
*
ilimit
;
};
/* Encapsulates all information for the regulators driver */
struct
da9063_regulators
{
int
irq_ldo_lim
;
int
irq_uvov
;
unsigned
n_regulators
;
/* Array size to be defined during init. Keep at end. */
struct
da9063_regulator
regulator
[
0
];
};
/* BUCK modes for DA9063 */
enum
{
BUCK_MODE_MANUAL
,
/* 0 */
BUCK_MODE_SLEEP
,
/* 1 */
BUCK_MODE_SYNC
,
/* 2 */
BUCK_MODE_AUTO
/* 3 */
};
/* Regulator operations */
/* Current limits array (in uA) for BCORE1, BCORE2, BPRO.
Entry indexes corresponds to register values. */
static
const
int
da9063_buck_a_limits
[]
=
{
500000
,
600000
,
700000
,
800000
,
900000
,
1000000
,
1100000
,
1200000
,
1300000
,
1400000
,
1500000
,
1600000
,
1700000
,
1800000
,
1900000
,
2000000
};
/* Current limits array (in uA) for BMEM, BIO, BPERI.
Entry indexes corresponds to register values. */
static
const
int
da9063_buck_b_limits
[]
=
{
1500000
,
1600000
,
1700000
,
1800000
,
1900000
,
2000000
,
2100000
,
2200000
,
2300000
,
2400000
,
2500000
,
2600000
,
2700000
,
2800000
,
2900000
,
3000000
};
/* Current limits array (in uA) for merged BCORE1 and BCORE2.
Entry indexes corresponds to register values. */
static
const
int
da9063_bcores_merged_limits
[]
=
{
1000000
,
1200000
,
1400000
,
1600000
,
1800000
,
2000000
,
2200000
,
2400000
,
2600000
,
2800000
,
3000000
,
3200000
,
3400000
,
3600000
,
3800000
,
4000000
};
/* Current limits array (in uA) for merged BMEM and BIO.
Entry indexes corresponds to register values. */
static
const
int
da9063_bmem_bio_merged_limits
[]
=
{
3000000
,
3200000
,
3400000
,
3600000
,
3800000
,
4000000
,
4200000
,
4400000
,
4600000
,
4800000
,
5000000
,
5200000
,
5400000
,
5600000
,
5800000
,
6000000
};
static
int
da9063_set_current_limit
(
struct
regulator_dev
*
rdev
,
int
min_uA
,
int
max_uA
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
const
struct
da9063_regulator_info
*
rinfo
=
regl
->
info
;
int
n
,
tval
;
for
(
n
=
0
;
n
<
rinfo
->
n_current_limits
;
n
++
)
{
tval
=
rinfo
->
current_limits
[
n
];
if
(
tval
>=
min_uA
&&
tval
<=
max_uA
)
return
regmap_field_write
(
regl
->
ilimit
,
n
);
}
return
-
EINVAL
;
}
static
int
da9063_get_current_limit
(
struct
regulator_dev
*
rdev
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
const
struct
da9063_regulator_info
*
rinfo
=
regl
->
info
;
unsigned
int
sel
;
int
ret
;
ret
=
regmap_field_read
(
regl
->
ilimit
,
&
sel
);
if
(
ret
<
0
)
return
ret
;
if
(
sel
>=
rinfo
->
n_current_limits
)
sel
=
rinfo
->
n_current_limits
-
1
;
return
rinfo
->
current_limits
[
sel
];
}
static
int
da9063_buck_set_mode
(
struct
regulator_dev
*
rdev
,
unsigned
mode
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
unsigned
val
;
switch
(
mode
)
{
case
REGULATOR_MODE_FAST
:
val
=
BUCK_MODE_SYNC
;
break
;
case
REGULATOR_MODE_NORMAL
:
val
=
BUCK_MODE_AUTO
;
break
;
case
REGULATOR_MODE_STANDBY
:
val
=
BUCK_MODE_SLEEP
;
break
;
default:
return
-
EINVAL
;
}
return
regmap_field_write
(
regl
->
mode
,
val
);
}
/*
* Bucks use single mode register field for normal operation
* and suspend state.
* There are 3 modes to map to: FAST, NORMAL, and STANDBY.
*/
static
unsigned
da9063_buck_get_mode
(
struct
regulator_dev
*
rdev
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
struct
regmap_field
*
field
;
unsigned
int
val
,
mode
=
0
;
int
ret
;
ret
=
regmap_field_read
(
regl
->
mode
,
&
val
);
if
(
ret
<
0
)
return
ret
;
switch
(
val
)
{
default:
case
BUCK_MODE_MANUAL
:
mode
=
REGULATOR_MODE_FAST
|
REGULATOR_MODE_STANDBY
;
/* Sleep flag bit decides the mode */
break
;
case
BUCK_MODE_SLEEP
:
return
REGULATOR_MODE_STANDBY
;
case
BUCK_MODE_SYNC
:
return
REGULATOR_MODE_FAST
;
case
BUCK_MODE_AUTO
:
return
REGULATOR_MODE_NORMAL
;
}
/* Detect current regulator state */
ret
=
regmap_field_read
(
regl
->
suspend
,
&
val
);
if
(
ret
<
0
)
return
0
;
/* Read regulator mode from proper register, depending on state */
if
(
val
)
field
=
regl
->
suspend_sleep
;
else
field
=
regl
->
sleep
;
ret
=
regmap_field_read
(
field
,
&
val
);
if
(
ret
<
0
)
return
0
;
if
(
val
)
mode
&=
REGULATOR_MODE_STANDBY
;
else
mode
&=
REGULATOR_MODE_NORMAL
|
REGULATOR_MODE_FAST
;
return
mode
;
}
/*
* LDOs use sleep flags - one for normal and one for suspend state.
* There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state.
*/
static
int
da9063_ldo_set_mode
(
struct
regulator_dev
*
rdev
,
unsigned
mode
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
unsigned
val
;
switch
(
mode
)
{
case
REGULATOR_MODE_NORMAL
:
val
=
0
;
break
;
case
REGULATOR_MODE_STANDBY
:
val
=
1
;
break
;
default:
return
-
EINVAL
;
}
return
regmap_field_write
(
regl
->
sleep
,
val
);
}
static
unsigned
da9063_ldo_get_mode
(
struct
regulator_dev
*
rdev
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
struct
regmap_field
*
field
;
int
ret
,
val
;
/* Detect current regulator state */
ret
=
regmap_field_read
(
regl
->
suspend
,
&
val
);
if
(
ret
<
0
)
return
0
;
/* Read regulator mode from proper register, depending on state */
if
(
val
)
field
=
regl
->
suspend_sleep
;
else
field
=
regl
->
sleep
;
ret
=
regmap_field_read
(
field
,
&
val
);
if
(
ret
<
0
)
return
0
;
if
(
val
)
return
REGULATOR_MODE_STANDBY
;
else
return
REGULATOR_MODE_NORMAL
;
}
static
int
da9063_buck_get_status
(
struct
regulator_dev
*
rdev
)
{
int
ret
=
regulator_is_enabled_regmap
(
rdev
);
if
(
ret
==
0
)
{
ret
=
REGULATOR_STATUS_OFF
;
}
else
if
(
ret
>
0
)
{
ret
=
da9063_buck_get_mode
(
rdev
);
if
(
ret
>
0
)
ret
=
regulator_mode_to_status
(
ret
);
else
if
(
ret
==
0
)
ret
=
-
EIO
;
}
return
ret
;
}
static
int
da9063_ldo_get_status
(
struct
regulator_dev
*
rdev
)
{
int
ret
=
regulator_is_enabled_regmap
(
rdev
);
if
(
ret
==
0
)
{
ret
=
REGULATOR_STATUS_OFF
;
}
else
if
(
ret
>
0
)
{
ret
=
da9063_ldo_get_mode
(
rdev
);
if
(
ret
>
0
)
ret
=
regulator_mode_to_status
(
ret
);
else
if
(
ret
==
0
)
ret
=
-
EIO
;
}
return
ret
;
}
static
int
da9063_set_suspend_voltage
(
struct
regulator_dev
*
rdev
,
int
uV
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
const
struct
da9063_regulator_info
*
rinfo
=
regl
->
info
;
int
ret
,
sel
;
sel
=
regulator_map_voltage_linear
(
rdev
,
uV
,
uV
);
if
(
sel
<
0
)
return
-
EINVAL
;
sel
<<=
ffs
(
rdev
->
desc
->
vsel_mask
)
-
1
;
ret
=
regmap_update_bits
(
regl
->
hw
->
regmap
,
rinfo
->
suspend_vsel_reg
,
rdev
->
desc
->
vsel_mask
,
sel
);
return
ret
;
}
static
int
da9063_suspend_enable
(
struct
regulator_dev
*
rdev
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
return
regmap_field_write
(
regl
->
suspend
,
1
);
}
static
int
da9063_suspend_disable
(
struct
regulator_dev
*
rdev
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
return
regmap_field_write
(
regl
->
suspend
,
0
);
}
static
int
da9063_buck_set_suspend_mode
(
struct
regulator_dev
*
rdev
,
unsigned
mode
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
int
val
;
switch
(
mode
)
{
case
REGULATOR_MODE_FAST
:
val
=
BUCK_MODE_SYNC
;
break
;
case
REGULATOR_MODE_NORMAL
:
val
=
BUCK_MODE_AUTO
;
break
;
case
REGULATOR_MODE_STANDBY
:
val
=
BUCK_MODE_SLEEP
;
break
;
default:
return
-
EINVAL
;
}
return
regmap_field_write
(
regl
->
mode
,
val
);
}
static
int
da9063_ldo_set_suspend_mode
(
struct
regulator_dev
*
rdev
,
unsigned
mode
)
{
struct
da9063_regulator
*
regl
=
rdev_get_drvdata
(
rdev
);
unsigned
val
;
switch
(
mode
)
{
case
REGULATOR_MODE_NORMAL
:
val
=
0
;
break
;
case
REGULATOR_MODE_STANDBY
:
val
=
1
;
break
;
default:
return
-
EINVAL
;
}
return
regmap_field_write
(
regl
->
suspend_sleep
,
val
);
}
static
struct
regulator_ops
da9063_buck_ops
=
{
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
list_voltage
=
regulator_list_voltage_linear
,
.
set_current_limit
=
da9063_set_current_limit
,
.
get_current_limit
=
da9063_get_current_limit
,
.
set_mode
=
da9063_buck_set_mode
,
.
get_mode
=
da9063_buck_get_mode
,
.
get_status
=
da9063_buck_get_status
,
.
set_suspend_voltage
=
da9063_set_suspend_voltage
,
.
set_suspend_enable
=
da9063_suspend_enable
,
.
set_suspend_disable
=
da9063_suspend_disable
,
.
set_suspend_mode
=
da9063_buck_set_suspend_mode
,
};
static
struct
regulator_ops
da9063_ldo_ops
=
{
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
list_voltage
=
regulator_list_voltage_linear
,
.
set_mode
=
da9063_ldo_set_mode
,
.
get_mode
=
da9063_ldo_get_mode
,
.
get_status
=
da9063_ldo_get_status
,
.
set_suspend_voltage
=
da9063_set_suspend_voltage
,
.
set_suspend_enable
=
da9063_suspend_enable
,
.
set_suspend_disable
=
da9063_suspend_disable
,
.
set_suspend_mode
=
da9063_ldo_set_suspend_mode
,
};
/* Info of regulators for DA9063 */
static
const
struct
da9063_regulator_info
da9063_regulator_info
[]
=
{
{
DA9063_BUCK
(
DA9063
,
BCORE1
,
300
,
10
,
1570
,
da9063_buck_a_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BCORE1
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBCORE1_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_C
,
DA9063_BCORE1_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BCORE2
,
300
,
10
,
1570
,
da9063_buck_a_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BCORE2
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBCORE2_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_C
,
DA9063_BCORE2_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BPRO
,
530
,
10
,
1800
,
da9063_buck_a_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BPRO
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBPRO_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_B
,
DA9063_BPRO_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BMEM
,
800
,
20
,
3340
,
da9063_buck_b_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BMEM
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBMEM_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_A
,
DA9063_BMEM_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BIO
,
800
,
20
,
3340
,
da9063_buck_b_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BIO
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_2
,
DA9063_VBIO_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_A
,
DA9063_BIO_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BPERI
,
800
,
20
,
3340
,
da9063_buck_b_limits
),
DA9063_BUCK_COMMON_FIELDS
(
BPERI
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBPERI_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_B
,
DA9063_BPERI_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BCORES_MERGED
,
300
,
10
,
1570
,
da9063_bcores_merged_limits
),
/* BCORES_MERGED uses the same register fields as BCORE1 */
DA9063_BUCK_COMMON_FIELDS
(
BCORE1
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBCORE1_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_C
,
DA9063_BCORE1_ILIM_MASK
),
},
{
DA9063_BUCK
(
DA9063
,
BMEM_BIO_MERGED
,
800
,
20
,
3340
,
da9063_bmem_bio_merged_limits
),
/* BMEM_BIO_MERGED uses the same register fields as BMEM */
DA9063_BUCK_COMMON_FIELDS
(
BMEM
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VBMEM_SEL
),
.
ilimit
=
BFIELD
(
DA9063_REG_BUCK_ILIM_A
,
DA9063_BMEM_ILIM_MASK
),
},
{
DA9063_LDO
(
DA9063
,
LDO1
,
600
,
20
,
1860
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VLDO1_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO2
,
600
,
20
,
1860
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VLDO2_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO3
,
900
,
20
,
3440
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_1
,
DA9063_VLDO3_SEL
),
.
oc_event
=
BFIELD
(
DA9063_REG_STATUS_D
,
DA9063_LDO3_LIM
),
},
{
DA9063_LDO
(
DA9063
,
LDO4
,
900
,
20
,
3440
),
.
suspend
=
BFIELD
(
DA9063_REG_DVC_2
,
DA9063_VLDO4_SEL
),
.
oc_event
=
BFIELD
(
DA9063_REG_STATUS_D
,
DA9063_LDO4_LIM
),
},
{
DA9063_LDO
(
DA9063
,
LDO5
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO5_CONT
,
DA9063_VLDO5_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO6
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO6_CONT
,
DA9063_VLDO6_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO7
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO7_CONT
,
DA9063_VLDO7_SEL
),
.
oc_event
=
BFIELD
(
DA9063_REG_STATUS_D
,
DA9063_LDO7_LIM
),
},
{
DA9063_LDO
(
DA9063
,
LDO8
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO8_CONT
,
DA9063_VLDO8_SEL
),
.
oc_event
=
BFIELD
(
DA9063_REG_STATUS_D
,
DA9063_LDO8_LIM
),
},
{
DA9063_LDO
(
DA9063
,
LDO9
,
950
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO9_CONT
,
DA9063_VLDO9_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO10
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO10_CONT
,
DA9063_VLDO10_SEL
),
},
{
DA9063_LDO
(
DA9063
,
LDO11
,
900
,
50
,
3600
),
.
suspend
=
BFIELD
(
DA9063_REG_LDO11_CONT
,
DA9063_VLDO11_SEL
),
.
oc_event
=
BFIELD
(
DA9063_REG_STATUS_D
,
DA9063_LDO11_LIM
),
},
};
/* Link chip model with regulators info table */
static
struct
da9063_dev_model
regulators_models
[]
=
{
{
.
regulator_info
=
da9063_regulator_info
,
.
n_regulators
=
ARRAY_SIZE
(
da9063_regulator_info
),
.
dev_model
=
PMIC_DA9063
,
},
{
}
};
/* Regulator interrupt handlers */
static
irqreturn_t
da9063_ldo_lim_event
(
int
irq
,
void
*
data
)
{
struct
da9063_regulators
*
regulators
=
data
;
struct
da9063
*
hw
=
regulators
->
regulator
[
0
].
hw
;
struct
da9063_regulator
*
regl
;
int
bits
,
i
,
ret
;
ret
=
regmap_read
(
hw
->
regmap
,
DA9063_REG_STATUS_D
,
&
bits
);
if
(
ret
<
0
)
return
IRQ_NONE
;
for
(
i
=
regulators
->
n_regulators
-
1
;
i
>=
0
;
i
--
)
{
regl
=
&
regulators
->
regulator
[
i
];
if
(
regl
->
info
->
oc_event
.
reg
!=
DA9063_REG_STATUS_D
)
continue
;
if
(
BIT
(
regl
->
info
->
oc_event
.
lsb
)
&
bits
)
regulator_notifier_call_chain
(
regl
->
rdev
,
REGULATOR_EVENT_OVER_CURRENT
,
NULL
);
}
return
IRQ_HANDLED
;
}
/*
* Probing and Initialisation functions
*/
static
const
struct
regulator_init_data
*
da9063_get_regulator_initdata
(
const
struct
da9063_regulators_pdata
*
regl_pdata
,
int
id
)
{
int
i
;
for
(
i
=
0
;
i
<
regl_pdata
->
n_regulators
;
i
++
)
{
if
(
id
==
regl_pdata
->
regulator_data
[
i
].
id
)
return
regl_pdata
->
regulator_data
[
i
].
initdata
;
}
return
NULL
;
}
#ifdef CONFIG_OF
static
struct
of_regulator_match
da9063_matches
[]
=
{
[
DA9063_ID_BCORE1
]
=
{
.
name
=
"bcore1"
},
[
DA9063_ID_BCORE2
]
=
{
.
name
=
"bcore2"
},
[
DA9063_ID_BPRO
]
=
{
.
name
=
"bpro"
,
},
[
DA9063_ID_BMEM
]
=
{
.
name
=
"bmem"
,
},
[
DA9063_ID_BIO
]
=
{
.
name
=
"bio"
,
},
[
DA9063_ID_BPERI
]
=
{
.
name
=
"bperi"
,
},
[
DA9063_ID_BCORES_MERGED
]
=
{
.
name
=
"bcores-merged"
},
[
DA9063_ID_BMEM_BIO_MERGED
]
=
{
.
name
=
"bmem-bio-merged"
,
},
[
DA9063_ID_LDO1
]
=
{
.
name
=
"ldo1"
,
},
[
DA9063_ID_LDO2
]
=
{
.
name
=
"ldo2"
,
},
[
DA9063_ID_LDO3
]
=
{
.
name
=
"ldo3"
,
},
[
DA9063_ID_LDO4
]
=
{
.
name
=
"ldo4"
,
},
[
DA9063_ID_LDO5
]
=
{
.
name
=
"ldo5"
,
},
[
DA9063_ID_LDO6
]
=
{
.
name
=
"ldo6"
,
},
[
DA9063_ID_LDO7
]
=
{
.
name
=
"ldo7"
,
},
[
DA9063_ID_LDO8
]
=
{
.
name
=
"ldo8"
,
},
[
DA9063_ID_LDO9
]
=
{
.
name
=
"ldo9"
,
},
[
DA9063_ID_LDO10
]
=
{
.
name
=
"ldo10"
,
},
[
DA9063_ID_LDO11
]
=
{
.
name
=
"ldo11"
,
},
};
static
struct
da9063_regulators_pdata
*
da9063_parse_regulators_dt
(
struct
platform_device
*
pdev
,
struct
of_regulator_match
**
da9063_reg_matches
)
{
struct
da9063_regulators_pdata
*
pdata
;
struct
da9063_regulator_data
*
rdata
;
struct
device_node
*
node
;
int
i
,
n
,
num
;
node
=
of_find_node_by_name
(
pdev
->
dev
.
parent
->
of_node
,
"regulators"
);
if
(
!
node
)
{
dev_err
(
&
pdev
->
dev
,
"Regulators device node not found
\n
"
);
return
ERR_PTR
(
-
ENODEV
);
}
num
=
of_regulator_match
(
&
pdev
->
dev
,
node
,
da9063_matches
,
ARRAY_SIZE
(
da9063_matches
));
if
(
num
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to match regulators
\n
"
);
return
ERR_PTR
(
-
EINVAL
);
}
pdata
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
pdata
),
GFP_KERNEL
);
if
(
!
pdata
)
return
ERR_PTR
(
-
ENOMEM
);
pdata
->
regulator_data
=
devm_kzalloc
(
&
pdev
->
dev
,
num
*
sizeof
(
*
pdata
->
regulator_data
),
GFP_KERNEL
);
if
(
!
pdata
->
regulator_data
)
return
ERR_PTR
(
-
ENOMEM
);
pdata
->
n_regulators
=
num
;
n
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
da9063_matches
);
i
++
)
{
if
(
!
da9063_matches
[
i
].
init_data
)
continue
;
rdata
=
&
pdata
->
regulator_data
[
n
];
rdata
->
id
=
i
;
rdata
->
initdata
=
da9063_matches
[
i
].
init_data
;
n
++
;
};
*
da9063_reg_matches
=
da9063_matches
;
return
pdata
;
}
#else
static
struct
da9063_regulators_pdata
*
da9063_parse_regulators_dt
(
struct
platform_device
*
pdev
,
struct
of_regulator_match
**
da9063_reg_matches
)
{
da9063_reg_matches
=
NULL
;
return
PTR_ERR
(
-
ENODEV
);
}
#endif
static
int
da9063_regulator_probe
(
struct
platform_device
*
pdev
)
{
struct
da9063
*
da9063
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
da9063_pdata
*
da9063_pdata
=
dev_get_platdata
(
da9063
->
dev
);
struct
of_regulator_match
*
da9063_reg_matches
;
struct
da9063_regulators_pdata
*
regl_pdata
;
const
struct
da9063_dev_model
*
model
;
struct
da9063_regulators
*
regulators
;
struct
da9063_regulator
*
regl
;
struct
regulator_config
config
;
bool
bcores_merged
,
bmem_bio_merged
;
int
id
,
irq
,
n
,
n_regulators
,
ret
,
val
;
size_t
size
;
regl_pdata
=
da9063_pdata
?
da9063_pdata
->
regulators_pdata
:
NULL
;
if
(
!
regl_pdata
)
regl_pdata
=
da9063_parse_regulators_dt
(
pdev
,
&
da9063_reg_matches
);
if
(
IS_ERR
(
regl_pdata
)
||
regl_pdata
->
n_regulators
==
0
)
{
dev_err
(
&
pdev
->
dev
,
"No regulators defined for the platform
\n
"
);
return
PTR_ERR
(
regl_pdata
);
}
/* Find regulators set for particular device model */
for
(
model
=
regulators_models
;
model
->
regulator_info
;
model
++
)
{
if
(
model
->
dev_model
==
da9063
->
model
)
break
;
}
if
(
!
model
->
regulator_info
)
{
dev_err
(
&
pdev
->
dev
,
"Chip model not recognised (%u)
\n
"
,
da9063
->
model
);
return
-
ENODEV
;
}
ret
=
regmap_read
(
da9063
->
regmap
,
DA9063_REG_CONFIG_H
,
&
val
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Error while reading BUCKs configuration
\n
"
);
return
-
EIO
;
}
bcores_merged
=
val
&
DA9063_BCORE_MERGE
;
bmem_bio_merged
=
val
&
DA9063_BUCK_MERGE
;
n_regulators
=
model
->
n_regulators
;
if
(
bcores_merged
)
n_regulators
-=
2
;
/* remove BCORE1, BCORE2 */
else
n_regulators
--
;
/* remove BCORES_MERGED */
if
(
bmem_bio_merged
)
n_regulators
-=
2
;
/* remove BMEM, BIO */
else
n_regulators
--
;
/* remove BMEM_BIO_MERGED */
/* Allocate memory required by usable regulators */
size
=
sizeof
(
struct
da9063_regulators
)
+
n_regulators
*
sizeof
(
struct
da9063_regulator
);
regulators
=
devm_kzalloc
(
&
pdev
->
dev
,
size
,
GFP_KERNEL
);
if
(
!
regulators
)
{
dev_err
(
&
pdev
->
dev
,
"No memory for regulators
\n
"
);
return
-
ENOMEM
;
}
regulators
->
n_regulators
=
n_regulators
;
platform_set_drvdata
(
pdev
,
regulators
);
/* Register all regulators declared in platform information */
n
=
0
;
id
=
0
;
while
(
n
<
regulators
->
n_regulators
)
{
/* Skip regulator IDs depending on merge mode configuration */
switch
(
id
)
{
case
DA9063_ID_BCORE1
:
case
DA9063_ID_BCORE2
:
if
(
bcores_merged
)
{
id
++
;
continue
;
}
break
;
case
DA9063_ID_BMEM
:
case
DA9063_ID_BIO
:
if
(
bmem_bio_merged
)
{
id
++
;
continue
;
}
break
;
case
DA9063_ID_BCORES_MERGED
:
if
(
!
bcores_merged
)
{
id
++
;
continue
;
}
break
;
case
DA9063_ID_BMEM_BIO_MERGED
:
if
(
!
bmem_bio_merged
)
{
id
++
;
continue
;
}
break
;
}
/* Initialise regulator structure */
regl
=
&
regulators
->
regulator
[
n
];
regl
->
hw
=
da9063
;
regl
->
info
=
&
model
->
regulator_info
[
id
];
regl
->
desc
=
regl
->
info
->
desc
;
regl
->
desc
.
type
=
REGULATOR_VOLTAGE
;
regl
->
desc
.
owner
=
THIS_MODULE
;
if
(
regl
->
info
->
mode
.
reg
)
regl
->
mode
=
devm_regmap_field_alloc
(
&
pdev
->
dev
,
da9063
->
regmap
,
regl
->
info
->
mode
);
if
(
regl
->
info
->
suspend
.
reg
)
regl
->
suspend
=
devm_regmap_field_alloc
(
&
pdev
->
dev
,
da9063
->
regmap
,
regl
->
info
->
suspend
);
if
(
regl
->
info
->
sleep
.
reg
)
regl
->
sleep
=
devm_regmap_field_alloc
(
&
pdev
->
dev
,
da9063
->
regmap
,
regl
->
info
->
sleep
);
if
(
regl
->
info
->
suspend_sleep
.
reg
)
regl
->
suspend_sleep
=
devm_regmap_field_alloc
(
&
pdev
->
dev
,
da9063
->
regmap
,
regl
->
info
->
suspend_sleep
);
if
(
regl
->
info
->
ilimit
.
reg
)
regl
->
ilimit
=
devm_regmap_field_alloc
(
&
pdev
->
dev
,
da9063
->
regmap
,
regl
->
info
->
ilimit
);
/* Register regulator */
memset
(
&
config
,
0
,
sizeof
(
config
));
config
.
dev
=
&
pdev
->
dev
;
config
.
init_data
=
da9063_get_regulator_initdata
(
regl_pdata
,
id
);
config
.
driver_data
=
regl
;
if
(
da9063_reg_matches
)
config
.
of_node
=
da9063_reg_matches
[
id
].
of_node
;
config
.
regmap
=
da9063
->
regmap
;
regl
->
rdev
=
regulator_register
(
&
regl
->
desc
,
&
config
);
if
(
IS_ERR
(
regl
->
rdev
))
{
dev_err
(
&
pdev
->
dev
,
"Failed to register %s regulator
\n
"
,
regl
->
desc
.
name
);
ret
=
PTR_ERR
(
regl
->
rdev
);
goto
err
;
}
id
++
;
n
++
;
}
/* LDOs overcurrent event support */
irq
=
platform_get_irq_byname
(
pdev
,
"LDO_LIM"
);
if
(
irq
<
0
)
{
ret
=
irq
;
dev_err
(
&
pdev
->
dev
,
"Failed to get IRQ.
\n
"
);
goto
err
;
}
regulators
->
irq_ldo_lim
=
regmap_irq_get_virq
(
da9063
->
regmap_irq
,
irq
);
if
(
regulators
->
irq_ldo_lim
>=
0
)
{
ret
=
request_threaded_irq
(
regulators
->
irq_ldo_lim
,
NULL
,
da9063_ldo_lim_event
,
IRQF_TRIGGER_LOW
|
IRQF_ONESHOT
,
"LDO_LIM"
,
regulators
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to request LDO_LIM IRQ.
\n
"
);
regulators
->
irq_ldo_lim
=
-
ENXIO
;
}
}
return
0
;
err:
/* Wind back regulators registeration */
while
(
--
n
>=
0
)
regulator_unregister
(
regulators
->
regulator
[
n
].
rdev
);
return
ret
;
}
static
int
da9063_regulator_remove
(
struct
platform_device
*
pdev
)
{
struct
da9063_regulators
*
regulators
=
platform_get_drvdata
(
pdev
);
struct
da9063_regulator
*
regl
;
free_irq
(
regulators
->
irq_ldo_lim
,
regulators
);
free_irq
(
regulators
->
irq_uvov
,
regulators
);
for
(
regl
=
&
regulators
->
regulator
[
regulators
->
n_regulators
-
1
];
regl
>=
&
regulators
->
regulator
[
0
];
regl
--
)
regulator_unregister
(
regl
->
rdev
);
return
0
;
}
static
struct
platform_driver
da9063_regulator_driver
=
{
.
driver
=
{
.
name
=
DA9063_DRVNAME_REGULATORS
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
da9063_regulator_probe
,
.
remove
=
da9063_regulator_remove
,
};
static
int
__init
da9063_regulator_init
(
void
)
{
return
platform_driver_register
(
&
da9063_regulator_driver
);
}
subsys_initcall
(
da9063_regulator_init
);
static
void
__exit
da9063_regulator_cleanup
(
void
)
{
platform_driver_unregister
(
&
da9063_regulator_driver
);
}
module_exit
(
da9063_regulator_cleanup
);
/* Module information */
MODULE_AUTHOR
(
"Krystian Garbaciak <krystian.garbaciak@diasemi.com>"
);
MODULE_DESCRIPTION
(
"DA9063 regulators driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"paltform:"
DA9063_DRVNAME_REGULATORS
);
drivers/regulator/da9210-regulator.c
0 → 100644
View file @
62696579
/*
* da9210-regulator.c - Regulator device driver for DA9210
* Copyright (C) 2013 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regmap.h>
#include "da9210-regulator.h"
struct
da9210
{
struct
regulator_dev
*
rdev
;
struct
regmap
*
regmap
;
};
static
const
struct
regmap_config
da9210_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
};
static
int
da9210_set_current_limit
(
struct
regulator_dev
*
rdev
,
int
min_uA
,
int
max_uA
);
static
int
da9210_get_current_limit
(
struct
regulator_dev
*
rdev
);
static
struct
regulator_ops
da9210_buck_ops
=
{
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
list_voltage
=
regulator_list_voltage_linear
,
.
set_current_limit
=
da9210_set_current_limit
,
.
get_current_limit
=
da9210_get_current_limit
,
};
/* Default limits measured in millivolts and milliamps */
#define DA9210_MIN_MV 300
#define DA9210_MAX_MV 1570
#define DA9210_STEP_MV 10
/* Current limits for buck (uA) indices corresponds with register values */
static
const
int
da9210_buck_limits
[]
=
{
1600000
,
1800000
,
2000000
,
2200000
,
2400000
,
2600000
,
2800000
,
3000000
,
3200000
,
3400000
,
3600000
,
3800000
,
4000000
,
4200000
,
4400000
,
4600000
};
static
const
struct
regulator_desc
da9210_reg
=
{
.
name
=
"DA9210"
,
.
id
=
0
,
.
ops
=
&
da9210_buck_ops
,
.
type
=
REGULATOR_VOLTAGE
,
.
n_voltages
=
((
DA9210_MAX_MV
-
DA9210_MIN_MV
)
/
DA9210_STEP_MV
)
+
1
,
.
min_uV
=
(
DA9210_MIN_MV
*
1000
),
.
uV_step
=
(
DA9210_STEP_MV
*
1000
),
.
vsel_reg
=
DA9210_REG_VBUCK_A
,
.
vsel_mask
=
DA9210_VBUCK_MASK
,
.
enable_reg
=
DA9210_REG_BUCK_CONT
,
.
enable_mask
=
DA9210_BUCK_EN
,
.
owner
=
THIS_MODULE
,
};
static
int
da9210_set_current_limit
(
struct
regulator_dev
*
rdev
,
int
min_uA
,
int
max_uA
)
{
struct
da9210
*
chip
=
rdev_get_drvdata
(
rdev
);
unsigned
int
sel
;
int
i
;
/* search for closest to maximum */
for
(
i
=
ARRAY_SIZE
(
da9210_buck_limits
)
-
1
;
i
>=
0
;
i
--
)
{
if
(
min_uA
<=
da9210_buck_limits
[
i
]
&&
max_uA
>=
da9210_buck_limits
[
i
])
{
sel
=
i
;
sel
=
sel
<<
DA9210_BUCK_ILIM_SHIFT
;
return
regmap_update_bits
(
chip
->
regmap
,
DA9210_REG_BUCK_ILIM
,
DA9210_BUCK_ILIM_MASK
,
sel
);
}
}
return
-
EINVAL
;
}
static
int
da9210_get_current_limit
(
struct
regulator_dev
*
rdev
)
{
struct
da9210
*
chip
=
rdev_get_drvdata
(
rdev
);
unsigned
int
data
;
unsigned
int
sel
;
int
ret
;
ret
=
regmap_read
(
chip
->
regmap
,
DA9210_REG_BUCK_ILIM
,
&
data
);
if
(
ret
<
0
)
return
ret
;
/* select one of 16 values: 0000 (1600mA) to 1111 (4600mA) */
sel
=
(
data
&
DA9210_BUCK_ILIM_MASK
)
>>
DA9210_BUCK_ILIM_SHIFT
;
return
da9210_buck_limits
[
sel
];
}
/*
* I2C driver interface functions
*/
static
int
da9210_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
da9210
*
chip
;
struct
da9210_pdata
*
pdata
=
i2c
->
dev
.
platform_data
;
struct
regulator_dev
*
rdev
=
NULL
;
struct
regulator_config
config
=
{
};
int
error
;
chip
=
devm_kzalloc
(
&
i2c
->
dev
,
sizeof
(
struct
da9210
),
GFP_KERNEL
);
if
(
NULL
==
chip
)
{
dev_err
(
&
i2c
->
dev
,
"Cannot kzalloc memory for regulator structure
\n
"
);
return
-
ENOMEM
;
}
chip
->
regmap
=
devm_regmap_init_i2c
(
i2c
,
&
da9210_regmap_config
);
if
(
IS_ERR
(
chip
->
regmap
))
{
error
=
PTR_ERR
(
chip
->
regmap
);
dev_err
(
&
i2c
->
dev
,
"Failed to allocate register map: %d
\n
"
,
error
);
return
error
;
}
config
.
dev
=
&
i2c
->
dev
;
if
(
pdata
)
config
.
init_data
=
&
pdata
->
da9210_constraints
;
config
.
driver_data
=
chip
;
config
.
regmap
=
chip
->
regmap
;
rdev
=
regulator_register
(
&
da9210_reg
,
&
config
);
if
(
IS_ERR
(
rdev
))
{
dev_err
(
&
i2c
->
dev
,
"Failed to register DA9210 regulator
\n
"
);
return
PTR_ERR
(
rdev
);
}
chip
->
rdev
=
rdev
;
i2c_set_clientdata
(
i2c
,
chip
);
return
0
;
}
static
int
da9210_i2c_remove
(
struct
i2c_client
*
i2c
)
{
struct
da9210
*
chip
=
i2c_get_clientdata
(
i2c
);
regulator_unregister
(
chip
->
rdev
);
return
0
;
}
static
const
struct
i2c_device_id
da9210_i2c_id
[]
=
{
{
"da9210"
,
0
},
{},
};
MODULE_DEVICE_TABLE
(
i2c
,
da9210_i2c_id
);
static
struct
i2c_driver
da9210_regulator_driver
=
{
.
driver
=
{
.
name
=
"da9210"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
da9210_i2c_probe
,
.
remove
=
da9210_i2c_remove
,
.
id_table
=
da9210_i2c_id
,
};
module_i2c_driver
(
da9210_regulator_driver
);
MODULE_AUTHOR
(
"S Twiss <stwiss.opensource@diasemi.com>"
);
MODULE_DESCRIPTION
(
"Regulator device driver for Dialog DA9210"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/regulator/da9210-regulator.h
0 → 100644
View file @
62696579
/*
* da9210-regulator.h - Regulator definitions for DA9210
* Copyright (C) 2013 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __DA9210_REGISTERS_H__
#define __DA9210_REGISTERS_H__
struct
da9210_pdata
{
struct
regulator_init_data
da9210_constraints
;
};
/* Page selection */
#define DA9210_REG_PAGE_CON 0x00
/* System Control and Event Registers */
#define DA9210_REG_STATUS_A 0x50
#define DA9210_REG_STATUS_B 0x51
#define DA9210_REG_EVENT_A 0x52
#define DA9210_REG_EVENT_B 0x53
#define DA9210_REG_MASK_A 0x54
#define DA9210_REG_MASK_B 0x55
#define DA9210_REG_CONTROL_A 0x56
/* GPIO Control Registers */
#define DA9210_REG_GPIO_0_1 0x58
#define DA9210_REG_GPIO_2_3 0x59
#define DA9210_REG_GPIO_4_5 0x5A
#define DA9210_REG_GPIO_6 0x5B
/* Regulator Registers */
#define DA9210_REG_BUCK_CONT 0x5D
#define DA9210_REG_BUCK_ILIM 0xD0
#define DA9210_REG_BUCK_CONF1 0xD1
#define DA9210_REG_BUCK_CONF2 0xD2
#define DA9210_REG_VBACK_AUTO 0xD4
#define DA9210_REG_VBACK_BASE 0xD5
#define DA9210_REG_VBACK_MAX_DVC_IF 0xD6
#define DA9210_REG_VBACK_DVC 0xD7
#define DA9210_REG_VBUCK_A 0xD8
#define DA9210_REG_VBUCK_B 0xD9
/* I2C Interface Settings */
#define DA9210_REG_INTERFACE 0x105
/* OTP */
#define DA9210_REG_OPT_COUNT 0x140
#define DA9210_REG_OPT_ADDR 0x141
#define DA9210_REG_OPT_DATA 0x142
/* Customer Trim and Configuration */
#define DA9210_REG_CONFIG_A 0x143
#define DA9210_REG_CONFIG_B 0x144
#define DA9210_REG_CONFIG_C 0x145
#define DA9210_REG_CONFIG_D 0x146
#define DA9210_REG_CONFIG_E 0x147
/*
* Registers bits
*/
/* DA9210_REG_PAGE_CON (addr=0x00) */
#define DA9210_PEG_PAGE_SHIFT 0
#define DA9210_REG_PAGE_MASK 0x0F
/* On I2C registers 0x00 - 0xFF */
#define DA9210_REG_PAGE0 0
/* On I2C registers 0x100 - 0x1FF */
#define DA9210_REG_PAGE2 2
#define DA9210_PAGE_WRITE_MODE 0x00
#define DA9210_REPEAT_WRITE_MODE 0x40
#define DA9210_PAGE_REVERT 0x80
/* DA9210_REG_STATUS_A (addr=0x50) */
#define DA9210_GPI0 0x01
#define DA9210_GPI1 0x02
#define DA9210_GPI2 0x04
#define DA9210_GPI3 0x08
#define DA9210_GPI4 0x10
#define DA9210_GPI5 0x20
#define DA9210_GPI6 0x40
/* DA9210_REG_EVENT_A (addr=0x52) */
#define DA9210_E_GPI0 0x01
#define DA9210_E_GPI1 0x02
#define DA9210_E_GPI2 0x04
#define DA9210_E_GPI3 0x08
#define DA9210_E_GPI4 0x10
#define DA9210_E_GPI5 0x20
#define DA9210_E_GPI6 0x40
/* DA9210_REG_EVENT_B (addr=0x53) */
#define DA9210_E_OVCURR 0x01
#define DA9210_E_NPWRGOOD 0x02
#define DA9210_E_TEMP_WARN 0x04
#define DA9210_E_TEMP_CRIT 0x08
#define DA9210_E_VMAX 0x10
/* DA9210_REG_MASK_A (addr=0x54) */
#define DA9210_M_GPI0 0x01
#define DA9210_M_GPI1 0x02
#define DA9210_M_GPI2 0x04
#define DA9210_M_GPI3 0x08
#define DA9210_M_GPI4 0x10
#define DA9210_M_GPI5 0x20
#define DA9210_M_GPI6 0x40
/* DA9210_REG_MASK_B (addr=0x55) */
#define DA9210_M_OVCURR 0x01
#define DA9210_M_NPWRGOOD 0x02
#define DA9210_M_TEMP_WARN 0x04
#define DA9210_M_TEMP_CRIT 0x08
#define DA9210_M_VMAX 0x10
/* DA9210_REG_CONTROL_A (addr=0x56) */
#define DA9210_DEBOUNCING_SHIFT 0
#define DA9210_DEBOUNCING_MASK 0x07
#define DA9210_SLEW_RATE_SHIFT 3
#define DA9210_SLEW_RATE_MASK 0x18
#define DA9210_V_LOCK 0x20
/* DA9210_REG_GPIO_0_1 (addr=0x58) */
#define DA9210_GPIO0_PIN_SHIFT 0
#define DA9210_GPIO0_PIN_MASK 0x03
#define DA9210_GPIO0_PIN_GPI 0x00
#define DA9210_GPIO0_PIN_GPO_OD 0x02
#define DA9210_GPIO0_PIN_GPO 0x03
#define DA9210_GPIO0_TYPE 0x04
#define DA9210_GPIO0_TYPE_GPI 0x00
#define DA9210_GPIO0_TYPE_GPO 0x04
#define DA9210_GPIO0_MODE 0x08
#define DA9210_GPIO1_PIN_SHIFT 4
#define DA9210_GPIO1_PIN_MASK 0x30
#define DA9210_GPIO1_PIN_GPI 0x00
#define DA9210_GPIO1_PIN_VERROR 0x10
#define DA9210_GPIO1_PIN_GPO_OD 0x20
#define DA9210_GPIO1_PIN_GPO 0x30
#define DA9210_GPIO1_TYPE_SHIFT 0x40
#define DA9210_GPIO1_TYPE_GPI 0x00
#define DA9210_GPIO1_TYPE_GPO 0x40
#define DA9210_GPIO1_MODE 0x80
/* DA9210_REG_GPIO_2_3 (addr=0x59) */
#define DA9210_GPIO2_PIN_SHIFT 0
#define DA9210_GPIO2_PIN_MASK 0x03
#define DA9210_GPIO2_PIN_GPI 0x00
#define DA9210_GPIO5_PIN_BUCK_CLK 0x10
#define DA9210_GPIO2_PIN_GPO_OD 0x02
#define DA9210_GPIO2_PIN_GPO 0x03
#define DA9210_GPIO2_TYPE 0x04
#define DA9210_GPIO2_TYPE_GPI 0x00
#define DA9210_GPIO2_TYPE_GPO 0x04
#define DA9210_GPIO2_MODE 0x08
#define DA9210_GPIO3_PIN_SHIFT 4
#define DA9210_GPIO3_PIN_MASK 0x30
#define DA9210_GPIO3_PIN_GPI 0x00
#define DA9210_GPIO3_PIN_IERROR 0x10
#define DA9210_GPIO3_PIN_GPO_OD 0x20
#define DA9210_GPIO3_PIN_GPO 0x30
#define DA9210_GPIO3_TYPE_SHIFT 0x40
#define DA9210_GPIO3_TYPE_GPI 0x00
#define DA9210_GPIO3_TYPE_GPO 0x40
#define DA9210_GPIO3_MODE 0x80
/* DA9210_REG_GPIO_4_5 (addr=0x5A) */
#define DA9210_GPIO4_PIN_SHIFT 0
#define DA9210_GPIO4_PIN_MASK 0x03
#define DA9210_GPIO4_PIN_GPI 0x00
#define DA9210_GPIO4_PIN_GPO_OD 0x02
#define DA9210_GPIO4_PIN_GPO 0x03
#define DA9210_GPIO4_TYPE 0x04
#define DA9210_GPIO4_TYPE_GPI 0x00
#define DA9210_GPIO4_TYPE_GPO 0x04
#define DA9210_GPIO4_MODE 0x08
#define DA9210_GPIO5_PIN_SHIFT 4
#define DA9210_GPIO5_PIN_MASK 0x30
#define DA9210_GPIO5_PIN_GPI 0x00
#define DA9210_GPIO5_PIN_INTERFACE 0x01
#define DA9210_GPIO5_PIN_GPO_OD 0x20
#define DA9210_GPIO5_PIN_GPO 0x30
#define DA9210_GPIO5_TYPE_SHIFT 0x40
#define DA9210_GPIO5_TYPE_GPI 0x00
#define DA9210_GPIO5_TYPE_GPO 0x40
#define DA9210_GPIO5_MODE 0x80
/* DA9210_REG_GPIO_6 (addr=0x5B) */
#define DA9210_GPIO6_PIN_SHIFT 0
#define DA9210_GPIO6_PIN_MASK 0x03
#define DA9210_GPIO6_PIN_GPI 0x00
#define DA9210_GPIO6_PIN_INTERFACE 0x01
#define DA9210_GPIO6_PIN_GPO_OD 0x02
#define DA9210_GPIO6_PIN_GPO 0x03
#define DA9210_GPIO6_TYPE 0x04
#define DA9210_GPIO6_TYPE_GPI 0x00
#define DA9210_GPIO6_TYPE_GPO 0x04
#define DA9210_GPIO6_MODE 0x08
/* DA9210_REG_BUCK_CONT (addr=0x5D) */
#define DA9210_BUCK_EN 0x01
#define DA9210_BUCK_GPI_SHIFT 1
#define DA9210_BUCK_GPI_MASK 0x06
#define DA9210_BUCK_GPI_OFF 0x00
#define DA9210_BUCK_GPI_GPIO0 0x02
#define DA9210_BUCK_GPI_GPIO3 0x04
#define DA9210_BUCK_GPI_GPIO4 0x06
#define DA9210_BUCK_PD_DIS 0x08
#define DA9210_VBUCK_SEL 0x10
#define DA9210_VBUCK_SEL_A 0x00
#define DA9210_VBUCK_SEL_B 0x10
#define DA9210_VBUCK_GPI_SHIFT 5
#define DA9210_VBUCK_GPI_MASK 0x60
#define DA9210_VBUCK_GPI_OFF 0x00
#define DA9210_VBUCK_GPI_GPIO0 0x20
#define DA9210_VBUCK_GPI_GPIO3 0x40
#define DA9210_VBUCK_GPI_GPIO4 0x60
#define DA9210_DVC_CTRL_EN 0x80
/* DA9210_REG_BUCK_ILIM (addr=0xD0) */
#define DA9210_BUCK_ILIM_SHIFT 0
#define DA9210_BUCK_ILIM_MASK 0x0F
#define DA9210_BUCK_IALARM 0x10
/* DA9210_REG_BUCK_CONF1 (addr=0xD1) */
#define DA9210_BUCK_MODE_SHIFT 0
#define DA9210_BUCK_MODE_MASK 0x03
#define DA9210_BUCK_MODE_MANUAL 0x00
#define DA9210_BUCK_MODE_SLEEP 0x01
#define DA9210_BUCK_MODE_SYNC 0x02
#define DA9210_BUCK_MODE_AUTO 0x03
#define DA9210_STARTUP_CTRL_SHIFT 2
#define DA9210_STARTUP_CTRL_MASK 0x1C
#define DA9210_PWR_DOWN_CTRL_SHIFT 5
#define DA9210_PWR_DOWN_CTRL_MASK 0xE0
/* DA9210_REG_BUCK_CONF2 (addr=0xD2) */
#define DA9210_PHASE_SEL_SHIFT 0
#define DA9210_PHASE_SEL_MASK 0x03
#define DA9210_FREQ_SEL 0x40
/* DA9210_REG_BUCK_AUTO (addr=0xD4) */
#define DA9210_VBUCK_AUTO_SHIFT 0
#define DA9210_VBUCK_AUTO_MASK 0x7F
/* DA9210_REG_BUCK_BASE (addr=0xD5) */
#define DA9210_VBUCK_BASE_SHIFT 0
#define DA9210_VBUCK_BASE_MASK 0x7F
/* DA9210_REG_VBUCK_MAX_DVC_IF (addr=0xD6) */
#define DA9210_VBUCK_MAX_SHIFT 0
#define DA9210_VBUCK_MAX_MASK 0x7F
#define DA9210_DVC_STEP_SIZE 0x80
#define DA9210_DVC_STEP_SIZE_10MV 0x00
#define DA9210_DVC_STEP_SIZE_20MV 0x80
/* DA9210_REG_VBUCK_DVC (addr=0xD7) */
#define DA9210_VBUCK_DVC_SHIFT 0
#define DA9210_VBUCK_DVC_MASK 0x7F
/* DA9210_REG_VBUCK_A/B (addr=0xD8/0xD9) */
#define DA9210_VBUCK_SHIFT 0
#define DA9210_VBUCK_MASK 0x7F
#define DA9210_VBUCK_BIAS 0
#define DA9210_BUCK_SL 0x80
/* DA9210_REG_INTERFACE (addr=0x105) */
#define DA9210_IF_BASE_ADDR_SHIFT 4
#define DA9210_IF_BASE_ADDR_MASK 0xF0
/* DA9210_REG_CONFIG_E (addr=0x147) */
#define DA9210_STAND_ALONE 0x01
#endif
/* __DA9210_REGISTERS_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment