Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC DEL 1ns 4cha
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
2
Issues
2
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
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