Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
4c1dde53
Commit
4c1dde53
authored
Apr 08, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Plain Diff
continue with sensor port i2c
parents
50663cc1
bc970067
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
197 additions
and
58 deletions
+197
-58
Makefile
src/drivers/elphel/Makefile
+3
-2
elphel393-mem.c
src/drivers/elphel/elphel393-mem.c
+28
-25
sensor_i2c.c
src/drivers/elphel/sensor_i2c.c
+166
-31
No files found.
src/drivers/elphel/Makefile
View file @
4c1dde53
...
@@ -8,5 +8,6 @@ obj-$(CONFIG_ELPHELDRVONMICROZED) += elphel393-mem.o
...
@@ -8,5 +8,6 @@ obj-$(CONFIG_ELPHELDRVONMICROZED) += elphel393-mem.o
obj-$(CONFIG_ELPHEL393_INIT)
+=
elphel393-init.o
obj-$(CONFIG_ELPHEL393_INIT)
+=
elphel393-init.o
obj-$(CONFIG_ELPHEL393)
+=
x393.o
obj-$(CONFIG_ELPHEL393)
+=
x393.o
obj-$(CONFIG_ELPHEL393)
+=
sensor_i2c.o
obj-$(CONFIG_ELPHEL393)
+=
sensor_i2c.o
fpgajtag-y
:=
fpgajtag353.o x393.o
obj-$(CONFIG_ELPHEL393)
+=
fpgajtag353.o
obj-$(CONFIG_ELPHEL393_EXTERNAL)
+=
fpgajtag.o
#fpgajtag-y := fpgajtag353.o x393.o
\ No newline at end of file
#obj-$(CONFIG_ELPHEL393_EXTERNAL)
+=
fpgajtag.o
\ No newline at end of file
src/drivers/elphel/elphel393-mem.c
View file @
4c1dde53
...
@@ -18,6 +18,10 @@
...
@@ -18,6 +18,10 @@
*! You should have received a copy of the GNU General Public License
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!****************************************************************************/
*!****************************************************************************/
#define DRV_NAME "elphel393-mem"
#define pr_fmt(fmt) DRV_NAME": " fmt
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of.h>
...
@@ -74,7 +78,7 @@ static int __init elphelmem_init(void)
...
@@ -74,7 +78,7 @@ static int __init elphelmem_init(void)
node
=
of_find_node_by_name
(
NULL
,
"elphel393-mem"
);
node
=
of_find_node_by_name
(
NULL
,
"elphel393-mem"
);
if
(
!
node
)
if
(
!
node
)
{
{
pr
intk
(
"DMA buffer allocation ERROR: No device tree node found
\n
"
);
pr
_err
(
"DMA buffer allocation ERROR: No device tree node found
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
...
@@ -116,34 +120,33 @@ static int __init elphelmem_init(void)
...
@@ -116,34 +120,33 @@ static int __init elphelmem_init(void)
// allocate continuous virtual memory range
// allocate continuous virtual memory range
// _elphel_buf.vaddr = kmalloc((_elphel_buf.size*PAGE_SIZE) ,GFP_KERNEL);
// _elphel_buf.vaddr = kmalloc((_elphel_buf.size*PAGE_SIZE) ,GFP_KERNEL);
_elphel_buf
.
vaddr
=
dma_alloc_coherent
(
NULL
,(
_elphel_buf
.
size
*
PAGE_SIZE
),
&
(
_elphel_buf
.
paddr
),
GFP_KERNEL
);
_elphel_buf
.
vaddr
=
dma_alloc_coherent
(
NULL
,(
_elphel_buf
.
size
*
PAGE_SIZE
),
&
(
_elphel_buf
.
paddr
),
GFP_KERNEL
);
if
(
_elphel_buf
.
p
addr
)
{
if
(
_elphel_buf
.
v
addr
)
{
pr
intk
(
"Allocated %u pages for DMA at address 0x%x
\n
"
,
(
u32
)
_elphel_buf
.
size
,
(
u32
)
_elphel_buf
.
paddr
);
pr
_info
(
"Allocated %u pages for DMA at address 0x%x
\n
"
,
(
u32
)
_elphel_buf
.
size
,
(
u32
)
_elphel_buf
.
paddr
);
}
else
{
}
else
{
pr
intk
(
"ERROR allocating coherent DMA memory buffer
"
);
pr
_err
(
"ERROR allocating coherent DMA memory buffer
\n
"
);
}
}
_elphel_buf
.
h2d_vaddr
=
kzalloc
((
_elphel_buf
.
h2d_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
_elphel_buf
.
h2d_vaddr
=
kzalloc
((
_elphel_buf
.
h2d_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
if
(
!
_elphel_buf
.
h2d_vaddr
){
if
(
!
_elphel_buf
.
h2d_vaddr
){
_elphel_buf
.
h2d_size
=
0
;
_elphel_buf
.
h2d_size
=
0
;
pr
intk
(
"ERROR allocating H2D DMA memory buffer
"
);
pr
_err
(
"ERROR allocating H2D DMA memory buffer
\n
"
);
}
}
_elphel_buf
.
d2h_vaddr
=
kzalloc
((
_elphel_buf
.
d2h_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
_elphel_buf
.
d2h_vaddr
=
kzalloc
((
_elphel_buf
.
d2h_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
if
(
!
_elphel_buf
.
d2h_vaddr
){
if
(
!
_elphel_buf
.
d2h_vaddr
){
_elphel_buf
.
d2h_size
=
0
;
_elphel_buf
.
d2h_size
=
0
;
pr
intk
(
"ERROR allocating D2H DMA memory buffer
"
);
pr
_err
(
"ERROR allocating D2H DMA memory buffer
\n
"
);
}
}
_elphel_buf
.
bidir_vaddr
=
kzalloc
((
_elphel_buf
.
bidir_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
_elphel_buf
.
bidir_vaddr
=
kzalloc
((
_elphel_buf
.
bidir_size
*
PAGE_SIZE
)
,
GFP_KERNEL
);
if
(
!
_elphel_buf
.
bidir_vaddr
){
if
(
!
_elphel_buf
.
bidir_vaddr
){
_elphel_buf
.
bidir_size
=
0
;
_elphel_buf
.
bidir_size
=
0
;
pr
intk
(
"ERROR allocating Bidirectional DMA memory buffer
"
);
pr
_err
(
"ERROR allocating Bidirectional DMA memory buffer
\n
"
);
}
}
pr_info
(
"Coherent buffer vaddr: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
vaddr
);
printk
(
"Coherent buffer vaddr: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
vaddr
);
pr_info
(
"Coherent buffer paddr: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
paddr
);
printk
(
"Coherent buffer paddr: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
paddr
);
pr_info
(
"Coherent buffer length: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
size
*
PAGE_SIZE
);
printk
(
"Coherent buffer length: 0x%08X
\n
"
,(
u32
)
pElphel_buf
->
size
*
PAGE_SIZE
);
return
0
;
return
0
;
}
}
...
@@ -155,7 +158,7 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
...
@@ -155,7 +158,7 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
*/
*/
static
void
__exit
elphelmem_exit
(
void
)
static
void
__exit
elphelmem_exit
(
void
)
{
{
printk
(
"DMA buffer disabled
\n
"
);
pr_info
(
"DMA buffer disabled
\n
"
);
}
}
...
@@ -240,7 +243,7 @@ static ssize_t sync_for_device_h2d(struct device *dev, struct device_attribute *
...
@@ -240,7 +243,7 @@ static ssize_t sync_for_device_h2d(struct device *dev, struct device_attribute *
paddr
=
_elphel_buf
.
h2d_paddr
;
paddr
=
_elphel_buf
.
h2d_paddr
;
len
=
_elphel_buf
.
h2d_size
*
PAGE_SIZE
;
len
=
_elphel_buf
.
h2d_size
*
PAGE_SIZE
;
}
}
pr
intk
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
pr
_info
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_TO_DEVICE
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_TO_DEVICE
);
return
count
;
return
count
;
...
@@ -255,7 +258,7 @@ static ssize_t sync_for_cpu_d2h(struct device *dev, struct device_attribute *att
...
@@ -255,7 +258,7 @@ static ssize_t sync_for_cpu_d2h(struct device *dev, struct device_attribute *att
paddr
=
_elphel_buf
.
d2h_paddr
;
paddr
=
_elphel_buf
.
d2h_paddr
;
len
=
_elphel_buf
.
d2h_size
*
PAGE_SIZE
;
len
=
_elphel_buf
.
d2h_size
*
PAGE_SIZE
;
}
}
printk
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
pr_info
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
dma_sync_single_for_cpu
(
dev
,
paddr
,
len
,
DMA_FROM_DEVICE
);
dma_sync_single_for_cpu
(
dev
,
paddr
,
len
,
DMA_FROM_DEVICE
);
return
count
;
return
count
;
...
@@ -271,7 +274,7 @@ static ssize_t sync_for_device_d2h(struct device *dev, struct device_attribute *
...
@@ -271,7 +274,7 @@ static ssize_t sync_for_device_d2h(struct device *dev, struct device_attribute *
paddr
=
_elphel_buf
.
d2h_paddr
;
paddr
=
_elphel_buf
.
d2h_paddr
;
len
=
_elphel_buf
.
d2h_size
*
PAGE_SIZE
;
len
=
_elphel_buf
.
d2h_size
*
PAGE_SIZE
;
}
}
printk
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
pr_info
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_FROM_DEVICE
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_FROM_DEVICE
);
return
count
;
return
count
;
...
@@ -286,7 +289,7 @@ static ssize_t sync_for_cpu_bidir(struct device *dev, struct device_attribute *a
...
@@ -286,7 +289,7 @@ static ssize_t sync_for_cpu_bidir(struct device *dev, struct device_attribute *a
paddr
=
_elphel_buf
.
bidir_paddr
;
paddr
=
_elphel_buf
.
bidir_paddr
;
len
=
_elphel_buf
.
bidir_size
*
PAGE_SIZE
;
len
=
_elphel_buf
.
bidir_size
*
PAGE_SIZE
;
}
}
printk
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
pr_info
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
dma_sync_single_for_cpu
(
dev
,
paddr
,
len
,
DMA_BIDIRECTIONAL
);
dma_sync_single_for_cpu
(
dev
,
paddr
,
len
,
DMA_BIDIRECTIONAL
);
return
count
;
return
count
;
...
@@ -302,7 +305,7 @@ static ssize_t sync_for_device_bidir(struct device *dev, struct device_attribute
...
@@ -302,7 +305,7 @@ static ssize_t sync_for_device_bidir(struct device *dev, struct device_attribute
paddr
=
_elphel_buf
.
bidir_paddr
;
paddr
=
_elphel_buf
.
bidir_paddr
;
len
=
_elphel_buf
.
bidir_size
*
PAGE_SIZE
;
len
=
_elphel_buf
.
bidir_size
*
PAGE_SIZE
;
}
}
printk
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
pr_info
(
"
\n
addr=0x%08x, size = 0x%08x
\n
"
,
paddr
,
len
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_BIDIRECTIONAL
);
dma_sync_single_for_device
(
dev
,
paddr
,
len
,
DMA_BIDIRECTIONAL
);
return
count
;
return
count
;
...
@@ -386,13 +389,13 @@ static int elphel393_mem_sysfs_register(struct platform_device *pdev)
...
@@ -386,13 +389,13 @@ static int elphel393_mem_sysfs_register(struct platform_device *pdev)
static
int
elphel393_mem_probe
(
struct
platform_device
*
pdev
)
static
int
elphel393_mem_probe
(
struct
platform_device
*
pdev
)
{
{
elphel393_mem_sysfs_register
(
pdev
);
elphel393_mem_sysfs_register
(
pdev
);
dev_info
(
&
pdev
->
dev
,
"Probing elphel393-mem
\n
"
);
pr_info
(
"Probing elphel393-mem
\n
"
);
if
(
_elphel_buf
.
h2d_vaddr
){
if
(
_elphel_buf
.
h2d_vaddr
){
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf
->
h2d_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
h2d_vaddr
,
(
_elphel_buf
.
h2d_size
*
PAGE_SIZE
),
DMA_TO_DEVICE
);
pElphel_buf
->
h2d_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
h2d_vaddr
,
(
_elphel_buf
.
h2d_size
*
PAGE_SIZE
),
DMA_TO_DEVICE
);
if
(
!
pElphel_buf
->
h2d_paddr
){
if
(
!
pElphel_buf
->
h2d_paddr
){
pr
intk
(
"ERROR in dma_map_single() for bidirectional buffer
"
);
pr
_err
(
"ERROR in dma_map_single() for bidirectional buffer
\n
"
);
return
0
;
return
0
;
}
}
// printk("H2D DMA buffer location:\t\t0x%08X\n", pElphel_buf->h2d_paddr);
// printk("H2D DMA buffer location:\t\t0x%08X\n", pElphel_buf->h2d_paddr);
...
@@ -402,7 +405,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
...
@@ -402,7 +405,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf
->
d2h_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
d2h_vaddr
,
(
_elphel_buf
.
d2h_size
*
PAGE_SIZE
),
DMA_FROM_DEVICE
);
pElphel_buf
->
d2h_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
d2h_vaddr
,
(
_elphel_buf
.
d2h_size
*
PAGE_SIZE
),
DMA_FROM_DEVICE
);
if
(
!
pElphel_buf
->
d2h_paddr
){
if
(
!
pElphel_buf
->
d2h_paddr
){
pr
intk
(
"ERROR in dma_map_single() for bidirectional buffer
"
);
pr
_err
(
"ERROR in dma_map_single() for bidirectional buffer
\n
"
);
return
0
;
return
0
;
}
}
// printk("D2H DMA buffer location:\t\t0x%08X\n", pElphel_buf->d2h_paddr);
// printk("D2H DMA buffer location:\t\t0x%08X\n", pElphel_buf->d2h_paddr);
...
@@ -413,7 +416,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
...
@@ -413,7 +416,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
// mapped as DMA_BIDIRECTIONAL, each time will be synchronized when passing control from soft to hard and back
pElphel_buf
->
bidir_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
bidir_vaddr
,
(
_elphel_buf
.
bidir_size
*
PAGE_SIZE
),
DMA_BIDIRECTIONAL
);
pElphel_buf
->
bidir_paddr
=
dma_map_single
(
&
pdev
->
dev
,
_elphel_buf
.
bidir_vaddr
,
(
_elphel_buf
.
bidir_size
*
PAGE_SIZE
),
DMA_BIDIRECTIONAL
);
if
(
!
pElphel_buf
->
bidir_paddr
){
if
(
!
pElphel_buf
->
bidir_paddr
){
pr
intk
(
"ERROR in dma_map_single() for bidirectional buffer
"
);
pr
_err
(
"ERROR in dma_map_single() for bidirectional buffer
\n
"
);
return
0
;
return
0
;
}
}
// printk("Bidirectional DMA buffer location:\t0x%08X\n", pElphel_buf->bidir_paddr);
// printk("Bidirectional DMA buffer location:\t0x%08X\n", pElphel_buf->bidir_paddr);
...
@@ -438,7 +441,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
...
@@ -438,7 +441,7 @@ static int elphel393_mem_probe(struct platform_device *pdev)
static
int
elphel393_mem_remove
(
struct
platform_device
*
pdev
)
static
int
elphel393_mem_remove
(
struct
platform_device
*
pdev
)
{
{
dev_info
(
&
pdev
->
dev
,
"Removing elphel393-mem"
);
pr_info
(
"Removing elphel393-mem"
);
return
0
;
return
0
;
}
}
...
@@ -452,7 +455,7 @@ static struct platform_driver elphel393_mem = {
...
@@ -452,7 +455,7 @@ static struct platform_driver elphel393_mem = {
.
probe
=
elphel393_mem_probe
,
.
probe
=
elphel393_mem_probe
,
.
remove
=
elphel393_mem_remove
,
.
remove
=
elphel393_mem_remove
,
.
driver
=
{
.
driver
=
{
.
name
=
"elphel393-mem"
,
.
name
=
DRV_NAME
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
elphel393_mem_of_match
,
.
of_match_table
=
elphel393_mem_of_match
,
.
pm
=
NULL
,
/* power management */
.
pm
=
NULL
,
/* power management */
...
@@ -463,5 +466,5 @@ module_platform_driver(elphel393_mem);
...
@@ -463,5 +466,5 @@ module_platform_driver(elphel393_mem);
module_init
(
elphelmem_init
);
module_init
(
elphelmem_init
);
module_exit
(
elphelmem_exit
);
module_exit
(
elphelmem_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Elphel, Inc."
);
MODULE_DESCRIPTION
(
"Reserve a large chunk of contiguous memory at boot"
);
src/drivers/elphel/sensor_i2c.c
View file @
4c1dde53
...
@@ -289,8 +289,8 @@ static ssize_t get_i2c_page_alloc(struct device *dev, struct device_attribute *a
...
@@ -289,8 +289,8 @@ static ssize_t get_i2c_page_alloc(struct device *dev, struct device_attribute *a
{
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
chn
=
get_channel_from_name
(
attr
)
;
int
page
;
int
page
;
if
(
sysfs_page
[
chn
]
>=
0
)
//
if (sysfs_page[chn]>=0)
return
-
EBUSY
;
//
return -EBUSY;
page
=
i2c_page_alloc
(
chn
);
page
=
i2c_page_alloc
(
chn
);
if
(
page
<
0
)
if
(
page
<
0
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -303,17 +303,30 @@ static ssize_t free_i2c_page(struct device *dev, struct device_attribute *attr,
...
@@ -303,17 +303,30 @@ static ssize_t free_i2c_page(struct device *dev, struct device_attribute *attr,
int
page
;
int
page
;
sscanf
(
buf
,
"%i"
,
&
page
);
sscanf
(
buf
,
"%i"
,
&
page
);
page
&=
0xff
;
page
&=
0xff
;
if
(
sysfs_page
[
chn
]
>=
0
)
// if (sysfs_page[chn] >= 0)
i2c_page_free
(
chn
,
page
);
// i2c_page_free(chn, page);
sysfs_page
[
chn
]
=
-
1
;
// free
// sysfs_page[chn] = -1; // free
i2c_page_free
(
chn
,
page
);
return
count
;
return
count
;
}
}
/* Set/get page number for reading */
static
ssize_t
set_i2c_page_inuse
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
page
;
sscanf
(
buf
,
"%i"
,
&
page
);
sysfs_page
[
chn
]
=
page
&
0xff
;
return
count
;
}
static
ssize_t
get_i2c_page_inuse
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
ssize_t
get_i2c_page_inuse
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
chn
=
get_channel_from_name
(
attr
)
;
return
sprintf
(
buf
,
"%d
\n
"
,
sysfs_page
[
chn
]);
return
sprintf
(
buf
,
"%d
\n
"
,
sysfs_page
[
chn
]);
}
}
// Get i2c table data as raw data (hex)
// Get i2c table data as raw data (hex)
static
ssize_t
get_i2c_tbl_raw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
ssize_t
get_i2c_tbl_raw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
{
...
@@ -322,49 +335,170 @@ static ssize_t get_i2c_tbl_raw(struct device *dev, struct device_attribute *attr
...
@@ -322,49 +335,170 @@ static ssize_t get_i2c_tbl_raw(struct device *dev, struct device_attribute *attr
if
(
page
<
0
)
if
(
page
<
0
)
return
-
ENXIO
;
/* No such device or address */
return
-
ENXIO
;
/* No such device or address */
return
sprintf
(
buf
,
"
%0x
08x
\n
"
,
i2c_pages_shadow
[(
chn
<<
8
)
+
(
page
&
0xff
)]);
return
sprintf
(
buf
,
"
0x%
08x
\n
"
,
i2c_pages_shadow
[(
chn
<<
8
)
+
(
page
&
0xff
)]);
}
}
static
ssize_t
set_i2c_tbl_raw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
static
ssize_t
set_i2c_tbl_raw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
chn
=
get_channel_from_name
(
attr
)
;
int
page
,
data
;
int
ni
,
page
,
data
;
sscanf
(
buf
,
"%i %i"
,
&
page
,
&
data
);
ni
=
sscanf
(
buf
,
"%i %i"
,
&
page
,
&
data
);
page
&=
0xff
;
if
(
ni
<
2
)
dev_err
(
dev
,
"Requires 2 parameters: page, data
\n
"
);
return
-
EINVAL
;
set_sensor_i2c_raw
(
chn
,
set_sensor_i2c_raw
(
chn
,
page
,
// index in lookup table
page
&
0xff
,
// index in lookup table
(
u32
)
data
);
// Bit delay - number of mclk periods in 1/4 of the SCL period
(
u32
)
data
);
// Bit delay - number of mclk periods in 1/4 of the SCL period
return
count
;
return
count
;
}
}
// Sysfs top
// Get/parse i2c table (hex)
static
ssize_t
get_i2c_tbl_human
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
x393_i2c_ctltbl_t
tb_data
;
int
chn
=
get_channel_from_name
(
attr
)
;
int
page
=
sysfs_page
[
chn
];
// currently selected page for sysfs reads
if
(
page
<
0
)
return
-
ENXIO
;
/* No such device or address */
tb_data
.
d32
=
i2c_pages_shadow
[(
chn
<<
8
)
+
(
page
&
0xff
)];
if
(
tb_data
.
rnw
){
return
sprintf
(
buf
,
"Read entry: chn=%d page=%d(0x%x) two_byte_addr=%d number bytes to read=%d bit_duration=%d
\n
"
,
chn
,
page
,
page
,
tb_data
.
nabrd
,
tb_data
.
nabrd
,
tb_data
.
nbrd
,
tb_data
.
dly
);
}
else
{
return
sprintf
(
buf
,
"Write entry: chn=%d page=%d(0x%x) sa=0x%02x rah=0x%02x nbw=%d bit_duration=%d
\n
"
,
chn
,
page
,
page
,
tb_data
.
sa
,
tb_data
.
rah
,
tb_data
.
nbwr
,
tb_data
.
dly
);
}
}
static
ssize_t
set_i2c_tbl_wr_human
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
ni
,
page
,
rah
,
sa7
,
nbwr
,
dly
;
ni
=
sscanf
(
buf
,
"%i %i %i %i %i"
,
&
page
,
&
sa7
,
&
rah
,
&
nbwr
,
&
dly
);
if
(
ni
<
2
)
dev_err
(
dev
,
"Requires 5 parameters: page, slave address (7 bit), high reg address byte, bytes to write (1..10), 1/4 scl period in mclk
\n
"
);
return
-
EINVAL
;
set_sensor_i2c_wr
(
chn
,
page
&
0xff
,
// index in lookup table
sa7
&
0x7f
,
// slave address (7 bit)
rah
&
0xff
,
// High byte of the i2c register address
nbwr
&
0xf
,
// Number of bytes to write (1..10)
dly
&
0xff
);
// Bit delay - number of mclk periods in 1/4 of the SCL period
return
count
;
}
static
DEVICE_ATTR
(
alloc0
,
SYSFS_PERMISSIONS
&
SYSFS_READONLY
,
get_i2c_page_alloc
,
NULL
);
static
ssize_t
set_i2c_tbl_rd_human
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
static
DEVICE_ATTR
(
alloc1
,
SYSFS_PERMISSIONS
&
SYSFS_READONLY
,
get_i2c_page_alloc
,
NULL
);
{
static
DEVICE_ATTR
(
alloc2
,
SYSFS_PERMISSIONS
&
SYSFS_READONLY
,
get_i2c_page_alloc
,
NULL
);
int
chn
=
get_channel_from_name
(
attr
)
;
static
DEVICE_ATTR
(
alloc3
,
SYSFS_PERMISSIONS
&
SYSFS_READONLY
,
get_i2c_page_alloc
,
NULL
);
int
ni
,
page
,
two_byte_addr
,
num_bytes
,
bit_delay
;
static
DEVICE_ATTR
(
page_in_use0
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
free_i2c_page
);
ni
=
sscanf
(
buf
,
"%i %i %i %i %i"
,
&
page
,
&
two_byte_addr
,
&
num_bytes
,
&
bit_delay
);
static
DEVICE_ATTR
(
page_in_use1
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
free_i2c_page
);
if
(
ni
<
2
)
static
DEVICE_ATTR
(
page_in_use2
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
free_i2c_page
);
dev_err
(
dev
,
"Requires 4 parameters: page, two byte addr (0 - 8bit,1 - 16 bit reg. addr), number of bytes to read, bytes to write (1..10), 1/4 scl period in mclk
\n
"
);
static
DEVICE_ATTR
(
page_in_use3
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
free_i2c_page
);
return
-
EINVAL
;
static
DEVICE_ATTR
(
tbl_raw0
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
set_sensor_i2c_rd
(
chn
,
static
DEVICE_ATTR
(
tbl_raw1
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
page
&
0xff
,
// index in lookup table
static
DEVICE_ATTR
(
tbl_raw2
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
two_byte_addr
&
1
,
// Number of address bytes (0 - one byte, 1 - two bytes)
static
DEVICE_ATTR
(
tbl_raw3
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
num_bytes
&
7
,
// Number of bytes to read (1..8, 0 means 8)
bit_delay
&
0xff
);
// Bit delay - number of mclk periods in 1/4 of the SCL period
return
count
;
}
static
ssize_t
set_i2c_read
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
ni
,
page
,
sa7
,
addr
;
ni
=
sscanf
(
buf
,
"%i %i %i"
,
&
page
,
&
sa7
,
addr
);
if
(
ni
<
3
)
dev_err
(
dev
,
"Requires 3 parameters: page, sa7, reg_addr
\n
"
);
return
-
EINVAL
;
page
&=
0xff
;
read_sensor_i2c
(
chn
,
page
&
0xff
,
// page (8 bits)
sa7
&
0x7f
,
// 7-bit i2c slave address
addr
&
0xffff
);
// 8/16 bit address return count;
}
// Get i2c read data from fifo
static
ssize_t
get_i2c_read
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
int
chn
=
get_channel_from_name
(
attr
)
;
int
page
=
sysfs_page
[
chn
];
// currently selected page for sysfs reads
if
(
page
<
0
)
return
-
ENXIO
;
/* No such device or address */
return
sprintf
(
buf
,
"%d
\n
"
,
read_sensor_i2c_fifo
(
chn
));
// <0 - not ready, 0..255 - data
}
// Get i2c read data from fifo
static
ssize_t
get_i2c_help
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
return
sprintf
(
buf
,
"Numeric suffix in file names selects sensor port
\n
"
"alloc*: read - allocate and return page, write <page> (any data) - free page
\n
"
"rd_page*: read/write page number used in read operations (-1 if none)
\n
"
"tbl_raw*: read - raw hex table value (for current rd_page), write <page> <data32> set page
\n
"
"tbl_wr*: read - decoded table entry for current rd_page, write <page> <sa7> <high_addr_byte> <bytes_to_write> <dly>
\n
"
"tbl_rd*: read - decoded table entry for current rd_page, write <page> <2-byte addr> <bytes_to_read> <dly>
\n
"
"tbl_rd* and tbl_wr* return same result when read. Delay is 8 bit, 250 - 200KHz SCL
\n
"
);
}
// Sysfs top
/* alloc*: read - allocate and return page, write (any data) - free page */
static
DEVICE_ATTR
(
alloc0
,
SYSFS_PERMISSIONS
,
get_i2c_page_alloc
,
free_i2c_page
);
static
DEVICE_ATTR
(
alloc1
,
SYSFS_PERMISSIONS
,
get_i2c_page_alloc
,
free_i2c_page
);
static
DEVICE_ATTR
(
alloc2
,
SYSFS_PERMISSIONS
,
get_i2c_page_alloc
,
free_i2c_page
);
static
DEVICE_ATTR
(
alloc3
,
SYSFS_PERMISSIONS
,
get_i2c_page_alloc
,
free_i2c_page
);
/* rd_page*: read/write page number used in read operations */
static
DEVICE_ATTR
(
rd_page0
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
set_i2c_page_inuse
);
static
DEVICE_ATTR
(
rd_page1
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
set_i2c_page_inuse
);
static
DEVICE_ATTR
(
rd_page2
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
set_i2c_page_inuse
);
static
DEVICE_ATTR
(
rd_page3
,
SYSFS_PERMISSIONS
,
get_i2c_page_inuse
,
set_i2c_page_inuse
);
static
DEVICE_ATTR
(
tbl_raw0
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
static
DEVICE_ATTR
(
tbl_raw1
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
static
DEVICE_ATTR
(
tbl_raw2
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
static
DEVICE_ATTR
(
tbl_raw3
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_raw
,
set_i2c_tbl_raw
);
static
DEVICE_ATTR
(
tbl_wr0
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_wr_human
);
static
DEVICE_ATTR
(
tbl_wr1
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_wr_human
);
static
DEVICE_ATTR
(
tbl_wr2
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_wr_human
);
static
DEVICE_ATTR
(
tbl_wr3
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_wr_human
);
static
DEVICE_ATTR
(
tbl_rd0
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_rd_human
);
static
DEVICE_ATTR
(
tbl_rd1
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_rd_human
);
static
DEVICE_ATTR
(
tbl_rd2
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_rd_human
);
static
DEVICE_ATTR
(
tbl_rd3
,
SYSFS_PERMISSIONS
,
get_i2c_tbl_human
,
set_i2c_tbl_rd_human
);
static
DEVICE_ATTR
(
i2c_rd0
,
SYSFS_PERMISSIONS
,
get_i2c_read
,
set_i2c_read
);
static
DEVICE_ATTR
(
i2c_rd1
,
SYSFS_PERMISSIONS
,
get_i2c_read
,
set_i2c_read
);
static
DEVICE_ATTR
(
i2c_rd2
,
SYSFS_PERMISSIONS
,
get_i2c_read
,
set_i2c_read
);
static
DEVICE_ATTR
(
i2c_rd3
,
SYSFS_PERMISSIONS
,
get_i2c_read
,
set_i2c_read
);
static
DEVICE_ATTR
(
help
,
SYSFS_PERMISSIONS
&
SYSFS_READONLY
,
get_i2c_help
,
NULL
);
static
struct
attribute
*
root_dev_attrs
[]
=
{
static
struct
attribute
*
root_dev_attrs
[]
=
{
&
dev_attr_alloc0
.
attr
,
&
dev_attr_alloc0
.
attr
,
&
dev_attr_alloc1
.
attr
,
&
dev_attr_alloc1
.
attr
,
&
dev_attr_alloc2
.
attr
,
&
dev_attr_alloc2
.
attr
,
&
dev_attr_alloc3
.
attr
,
&
dev_attr_alloc3
.
attr
,
&
dev_attr_
page_in_us
e0
.
attr
,
&
dev_attr_
rd_pag
e0
.
attr
,
&
dev_attr_
page_in_us
e1
.
attr
,
&
dev_attr_
rd_pag
e1
.
attr
,
&
dev_attr_
page_in_us
e2
.
attr
,
&
dev_attr_
rd_pag
e2
.
attr
,
&
dev_attr_
page_in_us
e3
.
attr
,
&
dev_attr_
rd_pag
e3
.
attr
,
&
dev_attr_tbl_raw0
.
attr
,
&
dev_attr_tbl_raw0
.
attr
,
&
dev_attr_tbl_raw1
.
attr
,
&
dev_attr_tbl_raw1
.
attr
,
&
dev_attr_tbl_raw2
.
attr
,
&
dev_attr_tbl_raw2
.
attr
,
&
dev_attr_tbl_raw3
.
attr
,
&
dev_attr_tbl_raw3
.
attr
,
&
dev_attr_tbl_wr0
.
attr
,
&
dev_attr_tbl_wr1
.
attr
,
&
dev_attr_tbl_wr2
.
attr
,
&
dev_attr_tbl_wr3
.
attr
,
&
dev_attr_tbl_rd0
.
attr
,
&
dev_attr_tbl_rd1
.
attr
,
&
dev_attr_tbl_rd2
.
attr
,
&
dev_attr_tbl_rd3
.
attr
,
&
dev_attr_i2c_rd0
.
attr
,
&
dev_attr_i2c_rd1
.
attr
,
&
dev_attr_i2c_rd2
.
attr
,
&
dev_attr_i2c_rd3
.
attr
,
&
dev_attr_help
.
attr
,
NULL
NULL
};
};
...
@@ -412,13 +546,14 @@ static int elphel393_sensor_i2c_probe(struct platform_device *pdev)
...
@@ -412,13 +546,14 @@ static int elphel393_sensor_i2c_probe(struct platform_device *pdev)
struct i2c_client *ltc3589_client;
struct i2c_client *ltc3589_client;
struct elphel393_pwr_data_t *clientdata = NULL;
struct elphel393_pwr_data_t *clientdata = NULL;
*/
*/
dev_info
(
&
pdev
->
dev
,
"Probing elphel393-sensor-i2c
\n
"
);
pr_info
(
"Probing elphel393-sensor-i2c
\n
"
);
elphel393_sens_i2c_sysfs_register
(
pdev
);
i2c_page_alloc_init
();
i2c_page_alloc_init
();
#if 0
#if 0
clientdata = devm_kzalloc(&pdev->dev, sizeof(*clientdata), GFP_KERNEL);
clientdata = devm_kzalloc(&pdev->dev, sizeof(*clientdata), GFP_KERNEL);
#endif
#endif
elphel393_sensor_i2c_init_of
(
pdev
);
elphel393_sensor_i2c_init_of
(
pdev
);
elphel393_sens_i2c_sysfs_register
(
pdev
);
pr_info
(
"done probing elphel393-sensor-i2c
\n
"
);
return
0
;
return
0
;
}
}
...
@@ -435,7 +570,7 @@ static struct of_device_id elphel393_sensor_i2c_of_match[] = {
...
@@ -435,7 +570,7 @@ static struct of_device_id elphel393_sensor_i2c_of_match[] = {
MODULE_DEVICE_TABLE
(
of
,
elphel393_sensor_i2c_of_match
);
MODULE_DEVICE_TABLE
(
of
,
elphel393_sensor_i2c_of_match
);
static
struct
platform_driver
elphel393_
pwr
=
{
static
struct
platform_driver
elphel393_
sensor_i2c
=
{
.
probe
=
elphel393_sensor_i2c_probe
,
.
probe
=
elphel393_sensor_i2c_probe
,
.
remove
=
elphel393_sensor_i2c_remove
,
.
remove
=
elphel393_sensor_i2c_remove
,
.
driver
=
{
.
driver
=
{
...
@@ -446,7 +581,7 @@ static struct platform_driver elphel393_pwr = {
...
@@ -446,7 +581,7 @@ static struct platform_driver elphel393_pwr = {
},
},
};
};
module_platform_driver
(
elphel393_
pwr
);
module_platform_driver
(
elphel393_
sensor_i2c
);
MODULE_AUTHOR
(
"Andrey Filippov <andrey@elphel.com>"
);
MODULE_AUTHOR
(
"Andrey Filippov <andrey@elphel.com>"
);
MODULE_DESCRIPTION
(
"Elphel 10393 sensor ports i2c"
);
MODULE_DESCRIPTION
(
"Elphel 10393 sensor ports i2c"
);
...
...
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