Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC DEL 1ns 4cha - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
FMC DEL 1ns 4cha - Software
Commits
465ea0ad
Commit
465ea0ad
authored
May 02, 2012
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
i2c: implemented read/write functions, not used yet
parent
1c0185fb
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
197 additions
and
1 deletion
+197
-1
fd-core.c
fd-core.c
+1
-1
fine-delay.h
fine-delay.h
+9
-0
i2c.c
i2c.c
+187
-0
No files found.
fd-core.c
View file @
465ea0ad
...
...
@@ -124,7 +124,7 @@ static struct fd_modlist mods[] = {
{
"reset-again"
,
fd_reset_again
},
SUBSYS
(
acam
),
SUBSYS
(
time
),
//
SUBSYS(i2c),
SUBSYS
(
i2c
),
SUBSYS
(
zio
),
};
...
...
fine-delay.h
View file @
465ea0ad
...
...
@@ -258,6 +258,15 @@ extern void fd_zio_exit(struct spec_fd *fd);
extern
int
fd_spec_init
(
void
);
extern
void
fd_spec_exit
(
void
);
/* Functions exported by i2c.c */
extern
int
fd_i2c_init
(
struct
spec_fd
*
fd
);
extern
void
fd_i2c_exit
(
struct
spec_fd
*
fd
);
extern
int
fd_eerom_read
(
struct
spec_fd
*
fd
,
int
i2c_addr
,
uint32_t
offset
,
uint8_t
*
buf
,
size_t
size
);
extern
int
fd_eeprom_write
(
struct
spec_fd
*
fd
,
int
i2c_addr
,
uint32_t
offset
,
uint8_t
*
buf
,
size_t
size
);
#endif
/* __KERNEL__ */
#endif
/* __FINE_DELAY_H__ */
i2c.c
View file @
465ea0ad
/*
* I2C access (on-board EEPROM)
*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <linux/io.h>
#include <linux/time.h>
#include "fine-delay.h"
#include "hw/fd_main_regs.h"
static
void
set_sda
(
struct
spec_fd
*
fd
,
int
val
)
{
uint32_t
reg
;
reg
=
fd_readl
(
fd
,
FD_REG_I2CR
)
&
~
FD_I2CR_SDA_OUT
;
if
(
val
)
reg
|=
FD_I2CR_SDA_OUT
;
fd_writel
(
fd
,
reg
,
FD_REG_I2CR
);
}
static
void
set_scl
(
struct
spec_fd
*
fd
,
int
val
)
{
uint32_t
reg
;
reg
=
fd_readl
(
fd
,
FD_REG_I2CR
)
&
~
FD_I2CR_SCL_OUT
;
if
(
val
)
reg
|=
FD_I2CR_SCL_OUT
;
fd_writel
(
fd
,
reg
,
FD_REG_I2CR
);
}
static
int
get_sda
(
struct
spec_fd
*
fd
)
{
return
fd_readl
(
fd
,
FD_REG_I2CR
)
&
FD_I2CR_SDA_IN
?
1
:
0
;
};
static
void
mi2c_start
(
struct
spec_fd
*
fd
)
{
set_sda
(
fd
,
0
);
set_scl
(
fd
,
0
);
}
static
void
mi2c_stop
(
struct
spec_fd
*
fd
)
{
set_sda
(
fd
,
0
);
set_scl
(
fd
,
1
);
set_sda
(
fd
,
1
);
}
int
mi2c_put_byte
(
struct
spec_fd
*
fd
,
int
data
)
{
int
i
;
int
ack
;
for
(
i
=
0
;
i
<
8
;
i
++
,
data
<<=
1
)
{
set_sda
(
fd
,
data
&
0x80
);
set_scl
(
fd
,
1
);
set_scl
(
fd
,
0
);
}
set_sda
(
fd
,
1
);
set_scl
(
fd
,
1
);
ack
=
get_sda
(
fd
);
set_scl
(
fd
,
0
);
set_sda
(
fd
,
0
);
return
ack
?
-
EIO
:
0
;
/* ack low == success */
}
int
mi2c_get_byte
(
struct
spec_fd
*
fd
,
unsigned
char
*
data
,
int
sendack
)
{
int
i
;
int
indata
=
0
;
/* assert: scl is low */
set_scl
(
fd
,
0
);
set_sda
(
fd
,
1
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
set_scl
(
fd
,
1
);
indata
<<=
1
;
if
(
get_sda
(
fd
))
indata
|=
0x01
;
set_scl
(
fd
,
0
);
}
set_sda
(
fd
,
(
sendack
?
0
:
1
));
set_scl
(
fd
,
1
);
set_scl
(
fd
,
0
);
set_sda
(
fd
,
0
);
*
data
=
indata
;
return
0
;
}
void
mi2c_init
(
struct
spec_fd
*
fd
)
{
set_scl
(
fd
,
1
);
set_sda
(
fd
,
1
);
}
void
mi2c_scan
(
struct
spec_fd
*
fd
)
{
int
i
;
for
(
i
=
0
;
i
<
256
;
i
+=
2
)
{
mi2c_start
(
fd
);
if
(
!
mi2c_put_byte
(
fd
,
i
))
printk
(
"%s: Found i2c device at 0x%x
\n
"
,
KBUILD_MODNAME
,
i
>>
1
);
mi2c_stop
(
fd
);
}
}
/* FIXME: this is very inefficient: read several bytes in a row instead */
int
fd_eeprom_read
(
struct
spec_fd
*
fd
,
int
i2c_addr
,
uint32_t
offset
,
uint8_t
*
buf
,
size_t
size
)
{
int
i
;
unsigned
char
c
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
mi2c_start
(
fd
);
if
(
mi2c_put_byte
(
fd
,
i2c_addr
<<
1
)
<
0
)
{
mi2c_stop
(
fd
);
return
-
EIO
;
}
mi2c_put_byte
(
fd
,
(
offset
>>
8
)
&
0xff
);
mi2c_put_byte
(
fd
,
offset
&
0xff
);
offset
++
;
mi2c_stop
(
fd
);
mi2c_start
(
fd
);
mi2c_put_byte
(
fd
,
(
i2c_addr
<<
1
)
|
1
);
mi2c_get_byte
(
fd
,
&
c
,
0
);
*
buf
++
=
c
;
mi2c_stop
(
fd
);
}
return
size
;
}
int
fd_eeprom_write
(
struct
spec_fd
*
fd
,
int
i2c_addr
,
uint32_t
offset
,
uint8_t
*
buf
,
size_t
size
)
{
int
i
,
busy
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
mi2c_start
(
fd
);
if
(
mi2c_put_byte
(
fd
,
i2c_addr
<<
1
)
<
0
)
{
mi2c_stop
(
fd
);
return
-
1
;
}
mi2c_put_byte
(
fd
,
(
offset
>>
8
)
&
0xff
);
mi2c_put_byte
(
fd
,
offset
&
0xff
);
mi2c_put_byte
(
fd
,
*
buf
++
);
offset
++
;
mi2c_stop
(
fd
);
do
{
/* wait until the chip becomes ready */
mi2c_start
(
fd
);
busy
=
mi2c_put_byte
(
fd
,
i2c_addr
<<
1
);
mi2c_stop
(
fd
);
}
while
(
busy
);
}
return
size
;
}
int
fd_i2c_init
(
struct
spec_fd
*
fd
)
{
mi2c_scan
(
fd
);
/* FIXME: read calibration parameters from 0x50*/
return
0
;
}
void
fd_i2c_exit
(
struct
spec_fd
*
fd
)
{
/* nothing to do */
}
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